blob: ac24a8da8a3bed8081cc5beb7efade3ebbd83998 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.db.model.spi.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.eclipse.persistence.tools.db.model.spi.ExternalColumn;
import org.eclipse.persistence.tools.utility.ObjectTools;
/**
* @see comment about defensive programming at JDBCExternalDatabase
*
* @version 2.6
*/
@SuppressWarnings("nls")
final class JDBCExternalColumn implements ExternalColumn {
private final String name;
private final String typeName;
private final int jdbcTypeCode;
private final int size;
private final int scale; // used by fixed point numbers only
private final boolean nullable;
private boolean primaryKey; // pseudo-final
// ********** constructor/initialization **********
/**
* Construct an external column with the data from the current
* row of the specified result set.
* @see java.sql.DatabaseMetaData#getColumns(String, String, String, String)
*/
JDBCExternalColumn(ResultSet resultSet) throws SQLException {
super();
// the name is required, the other settings can be fudged
this.name = resultSet.getString(4).trim(); // COLUMN_NAME
if (this.name.length() == 0) {
throw new IllegalStateException("empty column name");
}
this.typeName = this.typeNameFrom(resultSet);
this.jdbcTypeCode = this.jdbcTypeCodeFrom(resultSet);
this.size = this.sizeFrom(resultSet);
this.scale = this.scaleFrom(resultSet);
this.nullable = this.nullableFrom(resultSet);
// 'primaryKey' will be set later by the table
}
private String typeNameFrom(ResultSet resultSet) {
try {
return this.trim(resultSet.getString(6)); // TYPE_NAME
} catch (SQLException ex) {
// * Returns null if TYPE_NAME is not supported by the driver
return null;
}
}
private int jdbcTypeCodeFrom(ResultSet resultSet) {
try {
return resultSet.getInt(5); // DATA_TYPE
} catch (SQLException ex) {
// * Returns NULL(?) if DATA_TYPE is not supported by the driver
return Types.NULL;
}
}
private int sizeFrom(ResultSet resultSet) {
try {
return resultSet.getInt(7); // COLUMN_SIZE
} catch (SQLException ex) {
// * Returns 0 if COLUMN_SIZE is not supported by the driver
return 0;
}
}
private int scaleFrom(ResultSet resultSet) {
try {
return resultSet.getInt(9); // DECIMAL_DIGITS
} catch (SQLException ex) {
// * Returns 0 if DECIMAL_DIGITS is not supported by the driver
return 0;
}
}
/**
* use IS_NULLABLE, since NULLABLE is pretty much useless;
* confusing... see the JDK JavaDocs...
*/
private boolean nullableFrom(ResultSet resultSet) {
String jdbc_IS_NULLABLE = null;
try {
jdbc_IS_NULLABLE = resultSet.getString(18); // IS_NULLABLE
} catch (SQLException ex) {
// defensive - continue with 'null' if IS_NULLABLE is not supported by the driver
}
// * Returns fixed-length strings
// if this is "NO", the column is *definitely* required (NOT NULL);
// * Returns true
if ((jdbc_IS_NULLABLE != null) && jdbc_IS_NULLABLE.trim().toUpperCase().equals("NO")) {
return false;
}
// NULLABLE (column 11) cannot tell us anything *definite* except that
// * Returns true
return true;
}
/**
* trim down the specified string, to null if necessary
*/
private String trim(String s) {
if (s == null) {
return null;
}
s = s.trim();
return (s.length() == 0) ? null : s;
}
// ********** ExternalColumn implementation **********
/**
* the name should never be null or empty
* @see org.eclipse.persistence.tools.db.model.spi.ExternalColumn#getName()
*/
@Override
public String getName() {
return this.name;
}
/**
* the type name can be null if we have problems reading the result set
* @see org.eclipse.persistence.tools.db.model.spi.ExternalColumn#getTypeName()
*/
@Override
public String getTypeName() {
return this.typeName;
}
/**
* {@inheritDoc}
*/
@Override
public int getJDBCTypeCode() {
return this.jdbcTypeCode;
}
/**
* {@inheritDoc}
*/
@Override
public int getSize() {
return this.size;
}
/**
* {@inheritDoc}
*/
@Override
public int getScale() {
return this.scale;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isNullable() {
return this.nullable;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isPrimaryKey() {
return this.primaryKey;
}
// ********** queries **********
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return ObjectTools.toString(this, this.name);
}
// ********** behavior **********
/**
* the primary key flag is set by the table soon after construction
*/
void setPrimaryKey(boolean primaryKey) {
this.primaryKey = primaryKey;
}
}