in core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java [5314:5563]
public IValueMeta getValueFromSqlType(
IVariables variables,
DatabaseMeta databaseMeta,
String name,
ResultSetMetaData rm,
int index,
boolean ignoreLength,
boolean lazyConversion)
throws HopDatabaseException {
try {
int length = -1;
int precision = -1;
int valtype = IValueMeta.TYPE_NONE;
boolean isClob = false;
int type = rm.getColumnType(index);
boolean signed = false;
try {
signed = rm.isSigned(index);
} catch (Exception ignored) {
// This JDBC Driver doesn't support the isSigned method
// nothing more we can do here by catch the exception.
}
switch (type) {
case Types.CHAR, Types.VARCHAR, Types.NVARCHAR, Types.LONGVARCHAR:
// Character Large Object
valtype = IValueMeta.TYPE_STRING;
if (!ignoreLength) {
length = rm.getColumnDisplaySize(index);
}
break;
case Types.CLOB, Types.NCLOB:
valtype = IValueMeta.TYPE_STRING;
length = DatabaseMeta.CLOB_LENGTH;
isClob = true;
break;
case Types.BIGINT:
// verify Unsigned BIGINT overflow!
//
if (signed) {
valtype = IValueMeta.TYPE_INTEGER;
precision = 0; // Max 9.223.372.036.854.775.807
length = 15;
} else {
valtype = IValueMeta.TYPE_BIGNUMBER;
precision = 0; // Max 18.446.744.073.709.551.615
length = 16;
}
break;
case Types.INTEGER:
valtype = IValueMeta.TYPE_INTEGER;
precision = 0; // Max 2.147.483.647
length = 9;
break;
case Types.SMALLINT:
valtype = IValueMeta.TYPE_INTEGER;
precision = 0; // Max 32.767
length = 4;
break;
case Types.TINYINT:
valtype = IValueMeta.TYPE_INTEGER;
precision = 0; // Max 127
length = 2;
break;
case Types.DECIMAL, Types.DOUBLE, Types.FLOAT, Types.REAL, Types.NUMERIC:
valtype = IValueMeta.TYPE_NUMBER;
length = rm.getPrecision(index);
precision = rm.getScale(index);
if (length >= 126) {
length = -1;
}
if (precision >= 126) {
precision = -1;
}
if (type == Types.DOUBLE || type == Types.FLOAT || type == Types.REAL) {
if (precision == 0) {
precision = -1; // precision is obviously incorrect if the type if
// Double/Float/Real
}
// If we're dealing with PostgreSQL and double precision types
if (databaseMeta.getIDatabase().isPostgresVariant()
&& type == Types.DOUBLE
&& precision >= 16
&& length >= 16) {
precision = -1;
length = -1;
}
// MySQL: max resolution is double precision floating point (double)
// The (12,31) that is given back is not correct
if (databaseMeta.getIDatabase().isMySqlVariant() && precision >= length) {
precision = -1;
length = -1;
}
// if the length or precision needs a BIGNUMBER
if (length > 15 || precision > 15) {
valtype = IValueMeta.TYPE_BIGNUMBER;
}
} else {
if (precision == 0) {
if (length <= 18 && length > 0) { // Among others Oracle is affected
// here.
valtype = IValueMeta.TYPE_INTEGER; // Long can hold up to 18
// significant digits
} else if (length > 18) {
valtype = IValueMeta.TYPE_BIGNUMBER;
}
} else { // we have a precision: keep NUMBER or change to BIGNUMBER?
if (length > 15 || precision > 15) {
valtype = IValueMeta.TYPE_BIGNUMBER;
}
}
}
if (databaseMeta.getIDatabase().isPostgresVariant()
&& type == Types.NUMERIC
&& length == 0
&& precision == 0) {
// undefined size => arbitrary precision
valtype = IValueMeta.TYPE_BIGNUMBER;
length = -1;
precision = -1;
}
if (databaseMeta.getIDatabase().isOracleVariant()) {
if (precision == 0 && length == 38) {
valtype =
databaseMeta.getIDatabase().isStrictBigNumberInterpretation()
? TYPE_BIGNUMBER
: TYPE_INTEGER;
}
if (precision <= 0 && length <= 0) {
// undefined size: BIGNUMBER,
// precision on Oracle can be 38, too
// big for a Number type
valtype = IValueMeta.TYPE_BIGNUMBER;
length = -1;
precision = -1;
}
}
break;
case Types.TIMESTAMP:
if (databaseMeta.supportsTimestampDataType()) {
valtype = IValueMeta.TYPE_TIMESTAMP;
length = rm.getScale(index);
}
break;
case Types.DATE:
if (databaseMeta.getIDatabase().isTeradataVariant()) {
precision = 1;
}
case Types.TIME:
valtype = IValueMeta.TYPE_DATE;
//
if (databaseMeta.getIDatabase().isMySqlVariant()) {
String property =
databaseMeta.getConnectionProperties(variables).getProperty("yearIsDateType");
if (property != null
&& property.equalsIgnoreCase(CONST_FALSE)
&& rm.getColumnTypeName(index).equalsIgnoreCase("YEAR")) {
valtype = IValueMeta.TYPE_INTEGER;
precision = 0;
length = 4;
break;
}
}
break;
case Types.BOOLEAN, Types.BIT:
valtype = IValueMeta.TYPE_BOOLEAN;
break;
case Types.BINARY, Types.BLOB, Types.VARBINARY, Types.LONGVARBINARY:
valtype = IValueMeta.TYPE_BINARY;
if (databaseMeta.isDisplaySizeTwiceThePrecision()
&& (2 * rm.getPrecision(index)) == rm.getColumnDisplaySize(index)) {
// set the length for "CHAR(X) FOR BIT DATA"
length = rm.getPrecision(index);
} else if ((databaseMeta.getIDatabase().isOracleVariant())
&& (type == Types.VARBINARY || type == Types.LONGVARBINARY)) {
// set the length for Oracle "RAW" or "LONGRAW" data types
valtype = IValueMeta.TYPE_STRING;
length = rm.getColumnDisplaySize(index);
} else if (databaseMeta.isMySqlVariant()
&& (type == Types.VARBINARY || type == Types.LONGVARBINARY)) {
// don't call 'length = rm.getColumnDisplaySize(index);'
length = -1; // keep the length to -1, e.g. for string functions (e.g.
// CONCAT)
} else if (databaseMeta.getIDatabase().isSqliteVariant()) {
valtype = IValueMeta.TYPE_STRING;
} else {
length = -1;
}
precision = -1;
break;
default:
valtype = IValueMeta.TYPE_STRING;
precision = rm.getScale(index);
break;
}
IValueMeta v = ValueMetaFactory.createValueMeta(name, valtype);
v.setLength(length);
v.setPrecision(precision);
v.setLargeTextField(isClob);
getOriginalColumnMetadata(v, rm, index, ignoreLength);
// See if we need to enable lazy conversion...
//
if (lazyConversion && valtype == IValueMeta.TYPE_STRING) {
v.setStorageType(IValueMeta.STORAGE_TYPE_BINARY_STRING);
// TODO set some encoding to go with this.
// Also set the storage metadata. a copy of the parent, set to String too.
//
try {
IValueMeta storageMetaData = ValueMetaFactory.cloneValueMeta(v, IValueMeta.TYPE_STRING);
storageMetaData.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
v.setStorageMetadata(storageMetaData);
} catch (Exception e) {
throw new SQLException(e);
}
}
IValueMeta newV = null;
try {
newV = databaseMeta.getIDatabase().customizeValueFromSqlType(v, rm, index);
} catch (SQLException e) {
throw new SQLException(e);
}
return newV == null ? v : newV;
} catch (Exception e) {
throw new HopDatabaseException(
"Error determining value metadata from SQL resultset metadata", e);
}
}