/** * Base class for type objects. * * <p> * * @author fredt@users * @version 1.9.0 * @since 1.9.0 */ public abstract class Type { public final int type; final long precision; final int scale; Type(int type, long precision, int scale) { this.type = type; this.precision = (int) precision; this.scale = scale; } public long size() { return precision; } public int scale() { return scale; } public abstract int displaySize(); /** Returns the JDBC type number of type, if it exists, otherwise the HSQLDB / SQL type. */ public abstract int getJDBCTypeNumber(); /** Returns the JDBC class name of type, if it exists, otherwise the HSQLDB class name. */ public abstract String getJDBCClassName(); /** * Returns the generic SQL CLI type number of type, if it exists, otherwise the HSQLDB type. The * generic type is returned for DATETIME and INTERVAL types. */ public abstract int getSQLGenericTypeNumber(); /** Returns the specific SQL CLI type number of type, if it exists, otherwise the HSQLDB type */ public abstract int getSQLSpecificTypeNumber(); /** Returns the name of the type */ public abstract String getName(); /** Returns the full definition of the type, including parameters */ public abstract String getDefinition(); public abstract int compare(Object a, Object b); public abstract Object convertToTypeLimits(Object a) throws HsqlException; /** * Explicit casts are handled by this method. SQL standard 6.12 rules for enforcement of size, * precision and scale are implemented. For CHARACTER values, it performs truncation in all cases * of long strings. */ public Object castToType(Session session, Object a, Type type) throws HsqlException { return convertToType(session, a, type); } /** * Same as castToType except for CHARACTER values. Perform string truncation of trailing spaces * only. For other long strings, it raises an exception. */ public abstract Object convertToType(Session session, Object a, Type type) throws HsqlException; /** Converts the object to the given type. Used for JDBC conversions. */ public abstract Object convertToDefaultType(Object o) throws HsqlException; public abstract String convertToString(Object a); public abstract String convertToSQLString(Object a); public boolean isCharacterType() { return false; } public boolean isNumberType() { return false; } public boolean isIntegralType() { return false; } public boolean isDateTimeType() { return false; } public boolean isIntervalType() { return false; } public boolean isBinaryType() { return false; } public boolean isBooleanType() { return false; } public boolean isLobType() { return false; } public boolean acceptsPrecision() { return false; } public boolean requiresPrecision() { return false; } public boolean acceptsFractionalPrecision() { return false; } public boolean acceptsScale() { return false; } /** Common type used in comparison opertions. other must be comparable with this. */ public abstract Type getAggregateType(Type other) throws HsqlException; /** * Result type of combining values of two types in different opertions. other type is not allways * comparable with this, but a operation should be valid without any explicit CAST */ public abstract Type getCombinedType(Type other, int operation) throws HsqlException; public int compareToTypeRange(Object o) { return 0; } /** All arithmetic ops are called on the pre-determined Type object of the result */ public Object add(Object a, Object b) throws HsqlException { throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } public Object subtract(Object a, Object b) throws HsqlException { throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } public Object multiply(Object a, Object b) throws HsqlException { throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } public Object divide(Object a, Object b) throws HsqlException { throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } public Object concat(Session session, Object a, Object b) throws HsqlException { throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } public boolean equals(Object other) { if (other instanceof Type) { return ((Type) other).type == type && ((Type) other).precision == precision && ((Type) other).scale == scale; } return false; } // null type public static final Type SQL_ALL_TYPES = NullType.getNullType(); // character types public static final Type SQL_CHAR = new CharacterType(Types.SQL_CHAR, 0); public static final Type SQL_VARCHAR = new CharacterType(Types.SQL_VARCHAR, 0); public static final Type SQL_VARCHAR_MAX_WIDTH = new CharacterType( Types.SQL_VARCHAR, 0); // todo - needs max implementation defined width. used for parameters public static final ClobType SQL_CLOB = new ClobType(); public static final Type VARCHAR_IGNORECASE = new CharacterType(Types.VARCHAR_IGNORECASE, 0); // binary types public static final BinaryType SQL_BINARY = new BinaryType(Types.SQL_BINARY, 0); public static final BinaryType SQL_VARBINARY = new BinaryType(Types.SQL_VARBINARY, 0); public static final BlobType SQL_BLOB = new BlobType(); // other type public static final OtherType OTHER = OtherType.getOtherType(); // boolean type public static final BooleanType SQL_BOOLEAN = BooleanType.getBooleanType(); // number types public static final NumberType SQL_NUMERIC = new NumberType(Types.SQL_NUMERIC, NumberType.defaultNumericPrecision, 0); public static final NumberType SQL_DECIMAL = new NumberType(Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, 0); public static final NumberType SQL_DOUBLE = new NumberType(Types.SQL_DOUBLE, 0, 0); // public static final NumberType TINYINT = new NumberType(Types.TINYINT, NumberType.tinyintPrecision, 0); public static final NumberType SQL_SMALLINT = new NumberType(Types.SQL_SMALLINT, NumberType.smallintPrecision, 0); public static final NumberType SQL_INTEGER = new NumberType(Types.SQL_INTEGER, NumberType.integerPrecision, 0); public static final NumberType SQL_BIGINT = new NumberType(Types.SQL_BIGINT, NumberType.bigintPrecision, 0); // date time public static final DateTimeType SQL_DATE = new DateTimeType(Types.SQL_DATE, DateTimeType.defaultDatetimeFractionPrecision); public static final DateTimeType SQL_TIME = new DateTimeType(Types.SQL_TIME, DateTimeType.defaultDatetimeFractionPrecision); public static final DateTimeType SQL_TIMESTAMP = new DateTimeType(Types.SQL_TIMESTAMP, DateTimeType.defaultDatetimeFractionPrecision); // interval public static final IntervalType SQL_INTERVAL_YEAR = IntervalType.newIntervalType( Types.SQL_INTERVAL_YEAR, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MONTH = IntervalType.newIntervalType( Types.SQL_INTERVAL_MONTH, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_HOUR = IntervalType.newIntervalType( Types.SQL_INTERVAL_HOUR, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MINUTE = IntervalType.newIntervalType( Types.SQL_INTERVAL_MINUTE, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_SECOND, IntervalType.defaultIntervalPrecision, IntervalType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_YEAR_TO_MONTH = IntervalType.newIntervalType( Types.SQL_INTERVAL_YEAR_TO_MONTH, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_HOUR = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_HOUR, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_MINUTE = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_MINUTE, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_SECOND, IntervalType.defaultIntervalPrecision, IntervalType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_HOUR_TO_MINUTE = IntervalType.newIntervalType( Types.SQL_INTERVAL_HOUR_TO_MINUTE, IntervalType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_HOUR_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_HOUR_TO_SECOND, IntervalType.defaultIntervalPrecision, IntervalType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_MINUTE_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_MINUTE_TO_SECOND, IntervalType.defaultIntervalPrecision, IntervalType.defaultIntervalFractionPrecision); /** For literals */ public static Type getValueType(int type, Object value) { long precision = 0; int scale = 0; if (value != null) { switch (type) { case Types.SQL_INTEGER: case Types.SQL_BIGINT: case Types.SQL_DOUBLE: case Types.SQL_BOOLEAN: case Types.SQL_ALL_TYPES: break; case Types.SQL_CHAR: precision = value.toString().length(); break; case Types.SQL_BINARY: precision = ((BinaryData) value).length(); break; case Types.SQL_NUMERIC: precision = JavaSystem.precision((BigDecimal) value); scale = ((BigDecimal) value).scale(); break; default: throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } } try { return getType(type, 0, precision, scale); } catch (HsqlException e) { // exception should never be thrown throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } } public static Type getDefaultType(int type) { try { return getType(type, 0, 0, 0); } catch (HsqlException e) { // exception should never be thrown throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } } public static int getHSQLDBTypeCode(int jdbcTypeNumber) throws HsqlException { switch (jdbcTypeNumber) { case Types.BIGINT: return Types.SQL_BIGINT; case Types.LONGVARCHAR: return Types.SQL_VARCHAR; case Types.CLOB: return Types.SQL_CLOB; case Types.BINARY: return Types.SQL_BINARY; case Types.VARBINARY: case Types.LONGVARBINARY: return Types.SQL_VARBINARY; case Types.BLOB: return Types.SQL_BLOB; default: return jdbcTypeNumber; } } /** * translate an internal type number to JDBC type number if a type is not supported internally, it * is returned without translation * * @param i int * @return int */ public static int getJDBCTypeCode(int type) { switch (type) { case Types.SQL_BLOB: return Types.BLOB; case Types.SQL_CLOB: return Types.CLOB; case Types.SQL_BIGINT: return Types.BIGINT; case Types.SQL_BINARY: return Types.BINARY; case Types.SQL_VARBINARY: return Types.VARBINARY; default: return type; } } /** Enforces precision and scale limits on type */ public static Type getType(int type, int collation, long precision, int scale) throws HsqlException { switch (type) { case Types.SQL_ALL_TYPES: return null; // return SQL_ALL_TYPES; // needs changes to Expression type resolution case Types.SQL_CHAR: case Types.SQL_VARCHAR: case Types.VARCHAR_IGNORECASE: case Types.SQL_CLOB: return CharacterType.getCharacterType(type, precision); case Types.SQL_INTEGER: return SQL_INTEGER; case Types.SQL_SMALLINT: return SQL_SMALLINT; case Types.SQL_BIGINT: return SQL_BIGINT; case Types.TINYINT: return TINYINT; case Types.SQL_FLOAT: if (precision > 53) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE, "" + precision); } case Types.SQL_REAL: case Types.SQL_DOUBLE: return SQL_DOUBLE; case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: if (precision == 0) { precision = NumberType.defaultNumericPrecision; } return NumberType.getNumberType(type, precision, scale); case Types.SQL_BOOLEAN: return SQL_BOOLEAN; case Types.SQL_BINARY: case Types.SQL_VARBINARY: case Types.SQL_BLOB: return BinaryType.getBinaryType(type, precision); case Types.SQL_DATE: case Types.SQL_TIME: case Types.SQL_TIMESTAMP: return DateTimeType.getDateTimeType(type, scale); case Types.SQL_INTERVAL_YEAR: case Types.SQL_INTERVAL_YEAR_TO_MONTH: case Types.SQL_INTERVAL_MONTH: case Types.SQL_INTERVAL_DAY: case Types.SQL_INTERVAL_DAY_TO_HOUR: case Types.SQL_INTERVAL_DAY_TO_MINUTE: case Types.SQL_INTERVAL_DAY_TO_SECOND: case Types.SQL_INTERVAL_HOUR: case Types.SQL_INTERVAL_HOUR_TO_MINUTE: case Types.SQL_INTERVAL_HOUR_TO_SECOND: case Types.SQL_INTERVAL_MINUTE: case Types.SQL_INTERVAL_MINUTE_TO_SECOND: case Types.SQL_INTERVAL_SECOND: return IntervalType.getIntervalType(type, precision, scale); case Types.OTHER: return OTHER; default: throw Trace.runtimeError(Trace.UNSUPPORTED_INTERNAL_OPERATION, "Type"); } } public static Type getAggregatedType(Type add, Type existing) throws HsqlException { if (existing == null || existing.type == Types.SQL_ALL_TYPES) { return add; } if (add == null || add.type == Types.SQL_ALL_TYPES) { return existing; } return existing.getAggregateType(add); } public static IntValueHashMap typeAliases; public static IntValueHashMap typeNames; static { typeNames = new IntValueHashMap(37); typeNames.put("CHARACTER", Types.SQL_CHAR); typeNames.put("VARCHAR", Types.SQL_VARCHAR); typeNames.put("VARCHAR_IGNORECASE", Types.VARCHAR_IGNORECASE); typeNames.put("DATE", Types.SQL_DATE); typeNames.put("TIME", Types.SQL_TIME); typeNames.put("TIMESTAMP", Types.SQL_TIMESTAMP); typeNames.put("INTERVAL", Types.SQL_INTERVAL); typeNames.put("TINYINT", Types.TINYINT); typeNames.put("SMALLINT", Types.SQL_SMALLINT); typeNames.put("INTEGER", Types.SQL_INTEGER); typeNames.put("BIGINT", Types.SQL_BIGINT); typeNames.put("REAL", Types.SQL_REAL); typeNames.put("FLOAT", Types.SQL_FLOAT); typeNames.put("DOUBLE", Types.SQL_DOUBLE); typeNames.put("NUMERIC", Types.SQL_NUMERIC); typeNames.put("DECIMAL", Types.SQL_DECIMAL); typeNames.put("BOOLEAN", Types.SQL_BOOLEAN); typeNames.put("BINARY", Types.SQL_BINARY); typeNames.put("VARBINARY", Types.SQL_VARBINARY); typeNames.put("CLOB", Types.SQL_CLOB); typeNames.put("BLOB", Types.SQL_BLOB); typeNames.put("OTHER", Types.OTHER); // typeAliases = new IntValueHashMap(67, 1); typeAliases.put("CHAR", Types.SQL_CHAR); typeAliases.put("CHAR VARYING", Types.SQL_VARCHAR); typeAliases.put("CHARACTER VARYING", Types.SQL_VARCHAR); typeAliases.put("CHARACTER LARGE OBJECT", Types.SQL_CLOB); typeAliases.put("INT", Types.SQL_INTEGER); typeAliases.put("DEC", Types.SQL_DECIMAL); typeAliases.put("LONGVARCHAR", Types.SQL_VARCHAR); typeAliases.put("DATETIME", Types.SQL_TIMESTAMP); typeAliases.put("BIT", Types.SQL_BOOLEAN); typeAliases.put("LONGVARBINARY", Types.SQL_VARBINARY); typeAliases.put("OBJECT", Types.OTHER); } public static int getTypeNr(String name) throws HsqlException { int i = typeNames.get(name, Integer.MIN_VALUE); if (i == Integer.MIN_VALUE) { i = typeAliases.get(name, Integer.MIN_VALUE); } if (i == Integer.MIN_VALUE) { throw Trace.error(Trace.WRONG_DATA_TYPE, name); } return i; } /** * convertJavaToSQLType * * @param value Object * @param dataType Type * @return Object */ public static Object convertJavaToSQLType(Object a, Type dataType) { if (a instanceof byte[]) { return new BinaryData((byte[]) a, false); } else if (a instanceof java.sql.Time) { return new TimeData(((java.sql.Time) a).getTime()); } return a; } public static boolean isSupportedSQLType(int typeNumber) { try { if (getDefaultType(typeNumber) != null) { return true; } } catch (RuntimeException e) { return false; } return false; } }
/** * Base class for type objects. * * <p> * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 1.9.0 * @since 1.9.0 */ public abstract class Type implements SchemaObject, Cloneable { public static final Type[] emptyArray = new Type[] {}; // public final int typeComparisonGroup; public final int typeCode; public final long precision; public final int scale; public UserTypeModifier userTypeModifier; // public static final int defaultArrayCardinality = 1024; // Type(int typeGroup, int type, long precision, int scale) { this.typeComparisonGroup = typeGroup; this.typeCode = type; this.precision = precision; this.scale = scale; } // interface specific methods public final int getType() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getType(); } public final HsqlName getName() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getName(); } public final HsqlName getCatalogName() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getSchemaName().schema; } public final HsqlName getSchemaName() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getSchemaName(); } public final Grantee getOwner() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getOwner(); } public final OrderedHashSet getReferences() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getReferences(); } public final OrderedHashSet getComponents() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getComponents(); } public final void compile(Session session, SchemaObject parentObject) { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } userTypeModifier.compile(session); } /** * Retrieves the SQL character sequence required to (re)create the trigger, as a StringBuffer * * @return the SQL character sequence required to (re)create the trigger */ public String getSQL() { if (userTypeModifier == null) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } return userTypeModifier.getSQL(); } public long getChangeTimestamp() { return 0; } public Type duplicate() { try { return (Type) super.clone(); } catch (CloneNotSupportedException e) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } } public abstract int displaySize(); /** Returns the JDBC type number of type, if it exists, otherwise the HSQLDB / SQL type. */ public abstract int getJDBCTypeCode(); /** Returns the JDBC class name of type, if it exists, otherwise the HSQLDB class name. */ public abstract String getJDBCClassName(); public abstract Class getJDBCClass(); public Integer getJDBCScale() { return acceptsScale() ? ValuePool.getInt(scale) : null; } public int getJDBCPrecision() { return precision > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) precision; } /** * Returns the generic SQL CLI type number of type, if it exists, otherwise the HSQLDB type. The * generic type is returned for DATETIME and INTERVAL types. */ public int getSQLGenericTypeCode() { return typeCode; } /** Returns the name of the type */ public abstract String getNameString(); /** Returns the name of the type */ public String getFullNameString() { return getNameString(); } /** Returns the full definition of the type, including parameters */ abstract String getDefinition(); public final String getTypeDefinition() { if (userTypeModifier == null) { return getDefinition(); } return getName().getSchemaQualifiedStatementName(); } public abstract int compare(Session session, Object a, Object b); public abstract Object convertToTypeLimits(SessionInterface session, Object a); /** * Explicit casts are handled by this method. SQL standard 6.12 rules for enforcement of size, * precision and scale are implemented. For CHARACTER values, it performs truncation in all cases * of long strings. */ public Object castToType(SessionInterface session, Object a, Type type) { return convertToType(session, a, type); } /** * Same as castToType except for CHARACTER values. Perform string truncation of trailing spaces * only. For other long strings, it raises an exception. */ public abstract Object convertToType(SessionInterface session, Object a, Type type); /** * Convert type for JDBC reads. Same as convertToType, but supports non-standard SQL conversions * supported by JDBC */ public Object convertToTypeJDBC(SessionInterface session, Object a, Type otherType) { if (otherType.isLobType()) { throw Error.error(ErrorCode.X_42561); } return convertToType(session, a, otherType); } public Object convertJavaToSQL(SessionInterface session, Object a) { return a; } public Object convertSQLToJava(SessionInterface session, Object a) { return a; } /** Converts the object to the given type without limit checks. Used for JDBC writes. */ public abstract Object convertToDefaultType(SessionInterface sessionInterface, Object o); public abstract String convertToString(Object a); public abstract String convertToSQLString(Object a); public abstract boolean canConvertFrom(Type otherType); public boolean canBeAssignedFrom(Type otherType) { return otherType == null ? true : this.typeComparisonGroup == otherType.typeComparisonGroup; } public int arrayLimitCardinality() { return 0; } public Type collectionBaseType() { return null; } public boolean isArrayType() { return false; } public boolean isMultisetType() { return false; } public boolean isRowType() { return false; } public boolean isStructuredType() { return false; } public boolean isCharacterType() { return false; } public boolean isNumberType() { return false; } public boolean isIntegralType() { return false; } public boolean isExactNumberType() { return false; } public boolean isDateTimeType() { return false; } public boolean isDateTimeTypeWithZone() { return false; } public boolean isIntervalType() { return false; } public boolean isBinaryType() { return false; } public boolean isBooleanType() { return false; } public boolean isLobType() { return false; } public boolean isBitType() { return false; } public boolean isObjectType() { return false; } public boolean isDistinctType() { return userTypeModifier == null ? false : userTypeModifier.schemaObjectType == SchemaObject.TYPE; } public boolean isDomainType() { return userTypeModifier == null ? false : userTypeModifier.schemaObjectType == SchemaObject.DOMAIN; } public boolean acceptsPrecision() { return false; } public boolean requiresPrecision() { return false; } public long getMaxPrecision() { return 0; } public int getMaxScale() { return 0; } public int getPrecisionRadix() { return 0; } public boolean acceptsFractionalPrecision() { return false; } public boolean acceptsScale() { return false; } public int precedenceDegree(Type other) { if (other.typeCode == typeCode) { return 0; } return Integer.MIN_VALUE; } /** Common type used in comparison opertions. other must be comparable with this. */ public abstract Type getAggregateType(Type other); /** * Result type of combining values of two types in different opertions. other type is not allways * comparable with this, but a operation should be valid without any explicit CAST */ public abstract Type getCombinedType(Type other, int operation); public int compareToTypeRange(Object o) { return 0; } /** All arithmetic ops are called on the pre-determined Type object of the result */ public Object absolute(Object a) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object negate(Object a) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object add(Object a, Object b, Type otherType) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object subtract(Object a, Object b, Type otherType) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object multiply(Object a, Object b) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object divide(Object a, Object b) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public Object concat(Session session, Object a, Object b) { throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } public int cardinality(Session session, Object a) { return 0; } public boolean equals(Object other) { if (other == this) { return true; } if (other instanceof Type) { return ((Type) other).typeCode == typeCode && ((Type) other).precision == precision && ((Type) other).scale == scale && ((Type) other).userTypeModifier == userTypeModifier; } return false; } public int hashCode() { return typeCode + (int) precision << 8 + scale << 16; } /** @todo 1.9.0 - review all needs max implementation defined lengths, used for parameters */ // null type public static final Type SQL_ALL_TYPES = NullType.getNullType(); // character types public static final CharacterType SQL_CHAR = new CharacterType(Types.SQL_CHAR, 1); public static final CharacterType SQL_CHAR_DEFAULT = new CharacterType(Types.SQL_CHAR, CharacterType.defaultCharPrecision); public static final CharacterType SQL_VARCHAR = new CharacterType(Types.SQL_VARCHAR, 0); public static final CharacterType SQL_VARCHAR_DEFAULT = new CharacterType(Types.SQL_VARCHAR, CharacterType.defaultCharPrecision); public static final ClobType SQL_CLOB = new ClobType(ClobType.defaultClobSize); public static final CharacterType VARCHAR_IGNORECASE = new CharacterType(Types.VARCHAR_IGNORECASE, 0); public static final CharacterType VARCHAR_IGNORECASE_DEFAULT = new CharacterType(Types.VARCHAR_IGNORECASE, CharacterType.defaultCharPrecision); // binary types public static final BitType SQL_BIT = new BitType(Types.SQL_BIT, 1); public static final BitType SQL_BIT_VARYING = new BitType(Types.SQL_BIT_VARYING, 1); public static final BitType SQL_BIT_VARYING_MAX_LENGTH = new BitType(Types.SQL_BIT_VARYING, BitType.maxBitPrecision); // binary types public static final BinaryType SQL_BINARY = new BinaryType(Types.SQL_BINARY, 1); public static final BinaryType SQL_BINARY_DEFAULT = new BinaryType(Types.SQL_BINARY, 32 * 1024); public static final BinaryType SQL_VARBINARY = new BinaryType(Types.SQL_VARBINARY, 0); public static final BinaryType SQL_VARBINARY_DEFAULT = new BinaryType(Types.SQL_VARBINARY, 32 * 1024); public static final BlobType SQL_BLOB = new BlobType(BlobType.defaultBlobSize); // other type public static final OtherType OTHER = OtherType.getOtherType(); // boolean type public static final BooleanType SQL_BOOLEAN = BooleanType.getBooleanType(); // number types public static final NumberType SQL_NUMERIC = new NumberType(Types.SQL_NUMERIC, NumberType.defaultNumericPrecision, 0); public static final NumberType SQL_DECIMAL = new NumberType(Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, 0); public static final NumberType SQL_DECIMAL_DEFAULT = new NumberType( Types.SQL_DECIMAL, NumberType.defaultNumericPrecision, NumberType.defaultNumericScale); public static final NumberType SQL_DECIMAL_BIGINT_SQR = new NumberType(Types.SQL_DECIMAL, NumberType.bigintSquareNumericPrecision, 0); public static final NumberType SQL_DOUBLE = new NumberType(Types.SQL_DOUBLE, 0, 0); // public static final NumberType TINYINT = new NumberType(Types.TINYINT, NumberType.tinyintPrecision, 0); public static final NumberType SQL_SMALLINT = new NumberType(Types.SQL_SMALLINT, NumberType.smallintPrecision, 0); public static final NumberType SQL_INTEGER = new NumberType(Types.SQL_INTEGER, NumberType.integerPrecision, 0); public static final NumberType SQL_BIGINT = new NumberType(Types.SQL_BIGINT, NumberType.bigintPrecision, 0); // date time public static final DateTimeType SQL_DATE = new DateTimeType(Types.SQL_TIMESTAMP, Types.SQL_DATE, 0); public static final DateTimeType SQL_TIME = new DateTimeType(Types.SQL_TIME, Types.SQL_TIME, DTIType.defaultTimeFractionPrecision); public static final DateTimeType SQL_TIME_WITH_TIME_ZONE = new DateTimeType( Types.SQL_TIME, Types.SQL_TIME_WITH_TIME_ZONE, DTIType.defaultTimeFractionPrecision); public static final DateTimeType SQL_TIMESTAMP = new DateTimeType( Types.SQL_TIMESTAMP, Types.SQL_TIMESTAMP, DTIType.defaultTimestampFractionPrecision); public static final DateTimeType SQL_TIMESTAMP_WITH_TIME_ZONE = new DateTimeType( Types.SQL_TIMESTAMP, Types.SQL_TIMESTAMP_WITH_TIME_ZONE, DTIType.defaultTimestampFractionPrecision); public static final DateTimeType SQL_TIMESTAMP_NO_FRACTION = new DateTimeType(Types.SQL_TIMESTAMP, Types.SQL_TIMESTAMP, 0); // interval public static final IntervalType SQL_INTERVAL_YEAR = IntervalType.newIntervalType(Types.SQL_INTERVAL_YEAR, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MONTH = IntervalType.newIntervalType(Types.SQL_INTERVAL_MONTH, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY = IntervalType.newIntervalType(Types.SQL_INTERVAL_DAY, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_HOUR = IntervalType.newIntervalType(Types.SQL_INTERVAL_HOUR, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MINUTE = IntervalType.newIntervalType(Types.SQL_INTERVAL_MINUTE, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_SECOND, DTIType.defaultIntervalPrecision, DTIType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_SECOND_MAX_FRACTION = IntervalType.newIntervalType( Types.SQL_INTERVAL_SECOND, DTIType.defaultIntervalPrecision, DTIType.maxFractionPrecision); public static final IntervalType SQL_INTERVAL_YEAR_TO_MONTH = IntervalType.newIntervalType( Types.SQL_INTERVAL_YEAR_TO_MONTH, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_HOUR = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_HOUR, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_MINUTE = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_MINUTE, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_DAY_TO_SECOND, DTIType.defaultIntervalPrecision, DTIType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_HOUR_TO_MINUTE = IntervalType.newIntervalType( Types.SQL_INTERVAL_HOUR_TO_MINUTE, DTIType.defaultIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_HOUR_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_HOUR_TO_SECOND, DTIType.defaultIntervalPrecision, DTIType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_MINUTE_TO_SECOND = IntervalType.newIntervalType( Types.SQL_INTERVAL_MINUTE_TO_SECOND, DTIType.defaultIntervalPrecision, DTIType.defaultIntervalFractionPrecision); // public static final IntervalType SQL_INTERVAL_YEAR_MAX_PRECISION = IntervalType.newIntervalType(Types.SQL_INTERVAL_YEAR, DTIType.maxIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MONTH_MAX_PRECISION = IntervalType.newIntervalType(Types.SQL_INTERVAL_MONTH, DTIType.maxIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_DAY_MAX_PRECISION = IntervalType.newIntervalType(Types.SQL_INTERVAL_DAY, DTIType.maxIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_HOUR_MAX_PRECISION = IntervalType.newIntervalType(Types.SQL_INTERVAL_HOUR, DTIType.maxIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_MINUTE_MAX_PRECISION = IntervalType.newIntervalType(Types.SQL_INTERVAL_MINUTE, DTIType.maxIntervalPrecision, 0); public static final IntervalType SQL_INTERVAL_SECOND_MAX_PRECISION = IntervalType.newIntervalType( Types.SQL_INTERVAL_SECOND, DTIType.maxIntervalPrecision, DTIType.defaultIntervalFractionPrecision); public static final IntervalType SQL_INTERVAL_SECOND_MAX_FRACTION_MAX_PRECISION = IntervalType.newIntervalType( Types.SQL_INTERVAL_SECOND, DTIType.maxIntervalPrecision, DTIType.maxFractionPrecision); // public static final ArrayType SQL_ARRAY_ALL_TYPES = new ArrayType(SQL_ALL_TYPES, 0); public static ArrayType getDefaultArrayType(int type) { return new ArrayType(getDefaultType(type), Type.defaultArrayCardinality); } public static Type getDefaultType(int type) { try { return getType(type, 0, 0, 0); } catch (Exception e) { return null; } } public static Type getDefaultTypeWithSize(int type) { switch (type) { case Types.SQL_ALL_TYPES: return SQL_ALL_TYPES; case Types.SQL_CHAR: return SQL_CHAR_DEFAULT; case Types.SQL_VARCHAR: return SQL_VARCHAR_DEFAULT; case Types.VARCHAR_IGNORECASE: return VARCHAR_IGNORECASE_DEFAULT; case Types.SQL_CLOB: return SQL_CLOB; case Types.SQL_INTEGER: return SQL_INTEGER; case Types.SQL_SMALLINT: return SQL_SMALLINT; case Types.SQL_BIGINT: return SQL_BIGINT; case Types.TINYINT: return TINYINT; case Types.SQL_FLOAT: case Types.SQL_REAL: case Types.SQL_DOUBLE: return SQL_DOUBLE; case Types.SQL_NUMERIC: return SQL_NUMERIC; case Types.SQL_DECIMAL: return SQL_DECIMAL; case Types.SQL_BOOLEAN: return SQL_BOOLEAN; case Types.SQL_BINARY: return SQL_BINARY_DEFAULT; case Types.SQL_VARBINARY: return SQL_VARBINARY_DEFAULT; case Types.SQL_BLOB: return SQL_BLOB; case Types.SQL_BIT: return SQL_BIT; case Types.SQL_BIT_VARYING: return SQL_BIT_VARYING; case Types.SQL_DATE: return SQL_DATE; case Types.SQL_TIME: return SQL_TIME; case Types.SQL_TIME_WITH_TIME_ZONE: return SQL_TIME_WITH_TIME_ZONE; case Types.SQL_TIMESTAMP: return SQL_TIMESTAMP; case Types.SQL_TIMESTAMP_WITH_TIME_ZONE: return SQL_TIMESTAMP_WITH_TIME_ZONE; case Types.SQL_INTERVAL_YEAR: return SQL_INTERVAL_YEAR; case Types.SQL_INTERVAL_YEAR_TO_MONTH: return SQL_INTERVAL_YEAR_TO_MONTH; case Types.SQL_INTERVAL_MONTH: return SQL_INTERVAL_MONTH; case Types.SQL_INTERVAL_DAY: return SQL_INTERVAL_DAY; case Types.SQL_INTERVAL_DAY_TO_HOUR: return SQL_INTERVAL_DAY_TO_HOUR; case Types.SQL_INTERVAL_DAY_TO_MINUTE: return SQL_INTERVAL_DAY_TO_MINUTE; case Types.SQL_INTERVAL_DAY_TO_SECOND: return SQL_INTERVAL_DAY_TO_SECOND; case Types.SQL_INTERVAL_HOUR: return SQL_INTERVAL_HOUR; case Types.SQL_INTERVAL_HOUR_TO_MINUTE: return SQL_INTERVAL_HOUR_TO_MINUTE; case Types.SQL_INTERVAL_HOUR_TO_SECOND: return SQL_INTERVAL_HOUR_TO_SECOND; case Types.SQL_INTERVAL_MINUTE: return SQL_INTERVAL_MINUTE; case Types.SQL_INTERVAL_MINUTE_TO_SECOND: return SQL_INTERVAL_MINUTE_TO_SECOND; case Types.SQL_INTERVAL_SECOND: return SQL_INTERVAL_SECOND; case Types.OTHER: return OTHER; default: return null; } } public static int getHSQLDBTypeCode(int jdbcTypeNumber) { switch (jdbcTypeNumber) { case Types.BIGINT: return Types.SQL_BIGINT; case Types.LONGVARCHAR: return Types.SQL_VARCHAR; case Types.CLOB: return Types.SQL_CLOB; case Types.BINARY: return Types.SQL_BINARY; case Types.BIT: return Types.SQL_BIT_VARYING; case Types.VARBINARY: case Types.LONGVARBINARY: return Types.SQL_VARBINARY; case Types.BLOB: return Types.SQL_BLOB; default: return jdbcTypeNumber; } } /** * translate an internal type number to JDBC type number if a type is not supported internally, it * is returned without translation * * @param type int * @return int */ public static int getJDBCTypeCode(int type) { switch (type) { case Types.SQL_BLOB: return Types.BLOB; case Types.SQL_CLOB: return Types.CLOB; case Types.SQL_BIGINT: return Types.BIGINT; case Types.SQL_BINARY: return Types.BINARY; case Types.SQL_VARBINARY: return Types.VARBINARY; case Types.SQL_BIT: case Types.SQL_BIT_VARYING: return Types.BIT; default: return type; } } /** Enforces precision and scale limits on type */ public static Type getType(int type, int collation, long precision, int scale) { switch (type) { case Types.SQL_ALL_TYPES: return SQL_ALL_TYPES; // return SQL_ALL_TYPES; // needs changes to Expression type resolution case Types.SQL_CHAR: case Types.SQL_VARCHAR: case Types.VARCHAR_IGNORECASE: case Types.SQL_CLOB: return CharacterType.getCharacterType(type, precision); case Types.SQL_INTEGER: return SQL_INTEGER; case Types.SQL_SMALLINT: return SQL_SMALLINT; case Types.SQL_BIGINT: return SQL_BIGINT; case Types.TINYINT: return TINYINT; case Types.SQL_FLOAT: if (precision > 53) { throw Error.error(ErrorCode.X_42592, "" + precision); } // fall through case Types.SQL_REAL: case Types.SQL_DOUBLE: return SQL_DOUBLE; case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: if (precision == 0) { precision = NumberType.defaultNumericPrecision; } return NumberType.getNumberType(type, precision, scale); case Types.SQL_BOOLEAN: return SQL_BOOLEAN; case Types.SQL_BINARY: case Types.SQL_VARBINARY: case Types.SQL_BLOB: return BinaryType.getBinaryType(type, precision); case Types.SQL_BIT: case Types.SQL_BIT_VARYING: return BitType.getBitType(type, precision); case Types.SQL_DATE: case Types.SQL_TIME: case Types.SQL_TIME_WITH_TIME_ZONE: case Types.SQL_TIMESTAMP: case Types.SQL_TIMESTAMP_WITH_TIME_ZONE: return DateTimeType.getDateTimeType(type, scale); case Types.SQL_INTERVAL_YEAR: case Types.SQL_INTERVAL_YEAR_TO_MONTH: case Types.SQL_INTERVAL_MONTH: case Types.SQL_INTERVAL_DAY: case Types.SQL_INTERVAL_DAY_TO_HOUR: case Types.SQL_INTERVAL_DAY_TO_MINUTE: case Types.SQL_INTERVAL_DAY_TO_SECOND: case Types.SQL_INTERVAL_HOUR: case Types.SQL_INTERVAL_HOUR_TO_MINUTE: case Types.SQL_INTERVAL_HOUR_TO_SECOND: case Types.SQL_INTERVAL_MINUTE: case Types.SQL_INTERVAL_MINUTE_TO_SECOND: case Types.SQL_INTERVAL_SECOND: return IntervalType.getIntervalType(type, precision, scale); case Types.OTHER: return OTHER; default: throw Error.runtimeError(ErrorCode.U_S0500, "Type"); } } public static Type getAggregateType(Type add, Type existing) { if (existing == null || existing.typeCode == Types.SQL_ALL_TYPES) { return add; } if (add == null || add.typeCode == Types.SQL_ALL_TYPES) { return existing; } return existing.getAggregateType(add); } public static final IntValueHashMap typeAliases; public static final IntValueHashMap typeNames; static { typeNames = new IntValueHashMap(37); typeNames.put("CHARACTER", Types.SQL_CHAR); typeNames.put("VARCHAR", Types.SQL_VARCHAR); typeNames.put("VARCHAR_IGNORECASE", Types.VARCHAR_IGNORECASE); typeNames.put("DATE", Types.SQL_DATE); typeNames.put("TIME", Types.SQL_TIME); typeNames.put("TIMESTAMP", Types.SQL_TIMESTAMP); typeNames.put("INTERVAL", Types.SQL_INTERVAL); typeNames.put("TINYINT", Types.TINYINT); typeNames.put("SMALLINT", Types.SQL_SMALLINT); typeNames.put("INTEGER", Types.SQL_INTEGER); typeNames.put("BIGINT", Types.SQL_BIGINT); typeNames.put("REAL", Types.SQL_REAL); typeNames.put("FLOAT", Types.SQL_FLOAT); typeNames.put("DOUBLE", Types.SQL_DOUBLE); typeNames.put("NUMERIC", Types.SQL_NUMERIC); typeNames.put("DECIMAL", Types.SQL_DECIMAL); typeNames.put("BOOLEAN", Types.SQL_BOOLEAN); typeNames.put("BINARY", Types.SQL_BINARY); typeNames.put("VARBINARY", Types.SQL_VARBINARY); typeNames.put("CLOB", Types.SQL_CLOB); typeNames.put("BLOB", Types.SQL_BLOB); typeNames.put("BIT", Types.SQL_BIT); typeNames.put("OTHER", Types.OTHER); // typeAliases = new IntValueHashMap(64); typeAliases.put("CHAR", Types.SQL_CHAR); typeAliases.put("INT", Types.SQL_INTEGER); typeAliases.put("DEC", Types.SQL_DECIMAL); typeAliases.put("LONGVARCHAR", Types.LONGVARCHAR); typeAliases.put("DATETIME", Types.SQL_TIMESTAMP); typeAliases.put("LONGVARBINARY", Types.LONGVARBINARY); typeAliases.put("OBJECT", Types.OTHER); } public static int getTypeNr(String name) { int i = typeNames.get(name, Integer.MIN_VALUE); if (i == Integer.MIN_VALUE) { i = typeAliases.get(name, Integer.MIN_VALUE); } return i; } public static boolean isSupportedSQLType(int typeNumber) { if (getDefaultType(typeNumber) == null) { return false; } return true; } public static boolean matches(Type[] one, Type[] other) { for (int i = 0; i < one.length; i++) { if (one[i].typeCode != other[i].typeCode) { return false; } } return true; } }