--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.types.TypeId\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.iapi.types;\r
+\r
+import org.apache.derby.iapi.services.io.Formatable;\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.loader.ClassFactory;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.catalog.types.BaseTypeIdImpl;\r
+import org.apache.derby.catalog.types.DecimalTypeIdImpl;\r
+import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;\r
+\r
+import org.apache.derby.iapi.reference.Limits;\r
+\r
+import java.io.ObjectOutput;\r
+import java.io.ObjectInput;\r
+import java.io.IOException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.types.*;\r
+import org.apache.derby.iapi.types.*;\r
+\r
+import org.apache.derby.iapi.reference.JDBC20Translation;\r
+import org.apache.derby.iapi.reference.JDBC30Translation;\r
+\r
+import java.sql.Types;\r
+\r
+/**\r
+ * The TypeId interface provides methods to get information about datatype ids.\r
+ \r
+ <P>\r
+ * The equals(Object) method can be used to determine if two typeIds are for the same type,\r
+ * which defines type id equality.\r
+\r
+ *\r
+ */\r
+\r
+public final class TypeId implements Formatable\r
+{\r
+ /**\r
+ * Various fixed numbers related to datatypes.\r
+ */\r
+ public static final int LONGINT_PRECISION = 19;\r
+ public static final int LONGINT_SCALE = 0;\r
+ public static final int LONGINT_MAXWIDTH = 8;\r
+\r
+ public static final int INT_PRECISION = 10;\r
+ public static final int INT_SCALE = 0;\r
+ public static final int INT_MAXWIDTH = 4;\r
+\r
+ public static final int SMALLINT_PRECISION = 5;\r
+ public static final int SMALLINT_SCALE = 0;\r
+ public static final int SMALLINT_MAXWIDTH = 2;\r
+\r
+ public static final int TINYINT_PRECISION = 3;\r
+ public static final int TINYINT_SCALE = 0;\r
+ public static final int TINYINT_MAXWIDTH = 1;\r
+\r
+ // precision in number of bits \r
+ public static final int DOUBLE_PRECISION = 52;\r
+ // the ResultSetMetaData needs to have the precision for numeric data\r
+ // in decimal digits, rather than number of bits, so need a separate constant.\r
+ public static final int DOUBLE_PRECISION_IN_DIGITS = 15;\r
+ public static final int DOUBLE_SCALE = 0;\r
+ public static final int DOUBLE_MAXWIDTH = 8;\r
+\r
+ // precision in number of bits \r
+ public static final int REAL_PRECISION = 23;\r
+ // the ResultSetMetaData needs to have the precision for numeric data\r
+ // in decimal digits, rather than number of bits, so need a separate constant.\r
+ public static final int REAL_PRECISION_IN_DIGITS = 7;\r
+ public static final int REAL_SCALE = 0;\r
+ public static final int REAL_MAXWIDTH = 4;\r
+\r
+ public static final int DECIMAL_PRECISION = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;\r
+ public static final int DECIMAL_SCALE = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;\r
+ public static final int DECIMAL_MAXWIDTH = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;\r
+\r
+ public static final int BOOLEAN_MAXWIDTH = 1;\r
+\r
+ public static final int CHAR_MAXWIDTH = Limits.DB2_CHAR_MAXWIDTH;\r
+ public static final int VARCHAR_MAXWIDTH = Limits.DB2_VARCHAR_MAXWIDTH;\r
+ public static final int LONGVARCHAR_MAXWIDTH = Limits.DB2_LONGVARCHAR_MAXWIDTH;\r
+ public static final int BIT_MAXWIDTH = Limits.DB2_CHAR_MAXWIDTH;\r
+ public static final int VARBIT_MAXWIDTH = Limits.DB2_VARCHAR_MAXWIDTH;\r
+ public static final int LONGVARBIT_MAXWIDTH = Limits.DB2_LONGVARCHAR_MAXWIDTH;\r
+\r
+ // not supposed to be limited! 4096G should be ok(?), if Derby can handle...\r
+ public static final int BLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long\r
+ public static final int CLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long\r
+ public static final int XML_MAXWIDTH = Integer.MAX_VALUE;\r
+\r
+ // Max width for datetime values is the length of the\r
+ // string returned from a call to "toString()" on the\r
+ // java.sql.Date, java.sql.Time, and java.sql.Timestamp\r
+ // classes (the result of toString() on those classes\r
+ // is defined by the JDBC API). This value is also\r
+ // used as the "precision" for those types.\r
+ public static final int DATE_MAXWIDTH = 10; // yyyy-mm-dd\r
+ public static final int TIME_MAXWIDTH = 8; // hh:mm:ss\r
+ public static final int TIMESTAMP_MAXWIDTH = 26; // yyyy-mm-dd hh:mm:ss.ffffff\r
+\r
+ // Scale DOES exist for time values. For a TIMESTAMP value,\r
+ // it's 6 ('ffffff'); for a TIME value, it's 0 (because there\r
+ // are no fractional seconds). Note that date values do\r
+ // not have a scale.\r
+ public static final int TIME_SCALE = 0;\r
+ public static final int TIMESTAMP_SCALE = 6;\r
+\r
+ /* These define all the type names for SQL92 and JDBC \r
+ * NOTE: boolean is SQL3\r
+ */\r
+ //public static final String BIT_NAME = "BIT";\r
+ //public static final String VARBIT_NAME = "BIT VARYING";\r
+ //public static final String LONGVARBIT_NAME = "LONG BIT VARYING";\r
+\r
+ public static final String BIT_NAME = "CHAR () FOR BIT DATA";\r
+ public static final String VARBIT_NAME = "VARCHAR () FOR BIT DATA";\r
+ public static final String LONGVARBIT_NAME = "LONG VARCHAR FOR BIT DATA";\r
+ public static final String TINYINT_NAME = "TINYINT";\r
+ public static final String SMALLINT_NAME = "SMALLINT";\r
+ public static final String INTEGER_NAME = "INTEGER";\r
+ public static final String LONGINT_NAME = "BIGINT";\r
+ public static final String FLOAT_NAME = "FLOAT";\r
+ public static final String REAL_NAME = "REAL";\r
+ public static final String DOUBLE_NAME = "DOUBLE";\r
+ public static final String NUMERIC_NAME = "NUMERIC";\r
+ public static final String DECIMAL_NAME = "DECIMAL";\r
+ public static final String CHAR_NAME = "CHAR";\r
+ public static final String VARCHAR_NAME = "VARCHAR";\r
+ public static final String LONGVARCHAR_NAME = "LONG VARCHAR";\r
+ public static final String DATE_NAME = "DATE";\r
+ public static final String TIME_NAME = "TIME";\r
+ public static final String TIMESTAMP_NAME = "TIMESTAMP";\r
+ public static final String BINARY_NAME = "BINARY";\r
+ public static final String VARBINARY_NAME = "VARBINARY";\r
+ public static final String LONGVARBINARY_NAME = "LONGVARBINARY";\r
+ public static final String BOOLEAN_NAME = "BOOLEAN";\r
+ public static final String REF_NAME = "REF";\r
+ public static final String NATIONAL_CHAR_NAME = "NATIONAL CHAR";\r
+ public static final String NATIONAL_VARCHAR_NAME = "NATIONAL CHAR VARYING";\r
+ public static final String NATIONAL_LONGVARCHAR_NAME = "LONG NVARCHAR";\r
+ public static final String BLOB_NAME = "BLOB";\r
+ public static final String CLOB_NAME = "CLOB";\r
+ public static final String NCLOB_NAME = "NCLOB";\r
+\r
+ // Following use of "XML" is per SQL/XML (2003) spec,\r
+ // section "10.2 Type name determination".\r
+ public static final String XML_NAME = "XML";\r
+ \r
+ // ARRAY and STRUCT are JDBC 2.0 data types that are not\r
+ // supported by Derby.\r
+ public static final String ARRAY_NAME = "ARRAY";\r
+ public static final String STRUCT_NAME = "STRUCT";\r
+\r
+ // DATALINK is a JDBC 3.0 data type. Not supported by Derby.\r
+ public static final String DATALINK_NAME = "DATALINK";\r
+\r
+ // ROWID and SQLXML are new types in JDBC 4.0. Not supported\r
+ // by Derby.\r
+ public static final String ROWID_NAME = "ROWID";\r
+ public static final String SQLXML_NAME = "SQLXML";\r
+\r
+ /**\r
+ * The following constants define the type precedence hierarchy.\r
+ */\r
+ public static final int USER_PRECEDENCE = 1000;\r
+\r
+ public static final int XML_PRECEDENCE = 180;\r
+ public static final int BLOB_PRECEDENCE = 170;\r
+ public static final int LONGVARBIT_PRECEDENCE = 160;\r
+ public static final int VARBIT_PRECEDENCE = 150;\r
+ public static final int BIT_PRECEDENCE = 140;\r
+ public static final int BOOLEAN_PRECEDENCE = 130;\r
+ public static final int TIME_PRECEDENCE = 120;\r
+ public static final int TIMESTAMP_PRECEDENCE = 110;\r
+ public static final int DATE_PRECEDENCE = 100;\r
+ public static final int DOUBLE_PRECEDENCE = 90;\r
+ public static final int REAL_PRECEDENCE = 80;\r
+ public static final int DECIMAL_PRECEDENCE = 70;\r
+ public static final int NUMERIC_PRECEDENCE = 69;\r
+ public static final int LONGINT_PRECEDENCE = 60;\r
+ public static final int INT_PRECEDENCE = 50;\r
+ public static final int SMALLINT_PRECEDENCE = 40;\r
+ public static final int TINYINT_PRECEDENCE = 30;\r
+ public static final int REF_PRECEDENCE = 25;\r
+ public static final int CLOB_PRECEDENCE = 14;\r
+ public static final int LONGVARCHAR_PRECEDENCE = 12;\r
+ public static final int VARCHAR_PRECEDENCE = 10;\r
+ public static final int CHAR_PRECEDENCE = 0;\r
+\r
+ /*\r
+ ** Static runtime fields for typeIds\r
+ ** These are put here because the system needs them init time.\r
+ */\r
+ public static final TypeId BOOLEAN_ID = new TypeId(StoredFormatIds.BOOLEAN_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.BOOLEAN_TYPE_ID_IMPL));\r
+ public static final TypeId INTEGER_ID = new TypeId(StoredFormatIds.INT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.INT_TYPE_ID_IMPL));\r
+ public static final TypeId CHAR_ID = new TypeId(StoredFormatIds.CHAR_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.CHAR_TYPE_ID_IMPL));\r
+ /*\r
+ ** Others are created on demand by the getBuiltInTypeId(int),\r
+ ** if they are built-in (i.e.? Part of JDBC .Types),\r
+ ** or by getBuiltInTypeId(string) if they are REF_NAME type.\r
+ */\r
+\r
+ private static TypeId TINYINT_ID;\r
+ private static TypeId SMALLINT_ID;\r
+ private static TypeId LONGINT_ID;\r
+ private static TypeId REAL_ID;\r
+ private static TypeId DOUBLE_ID;\r
+ private static TypeId DECIMAL_ID;\r
+ private static TypeId NUMERIC_ID;\r
+ private static TypeId VARCHAR_ID;\r
+ private static TypeId DATE_ID;\r
+ private static TypeId TIME_ID;\r
+ private static TypeId TIMESTAMP_ID;\r
+ private static TypeId BIT_ID;\r
+ private static TypeId VARBIT_ID;\r
+ private static TypeId REF_ID;\r
+ private static TypeId LONGVARCHAR_ID;\r
+ private static TypeId LONGVARBIT_ID;\r
+\r
+ private static TypeId BLOB_ID;\r
+ private static TypeId CLOB_ID;\r
+ private static TypeId XML_ID;\r
+\r
+ /**\r
+ * Implementation of DECIMAL datatype for generating holders through getNull.\r
+ * Set by the booted DataValueFactory implementation.\r
+ */\r
+ static DataValueDescriptor decimalImplementation;\r
+\r
+ /*\r
+ ** Static methods to obtain TypeIds\r
+ */\r
+ /**\r
+ * Get a TypeId of the given JDBC type. This factory method is\r
+ * intended to be used for built-in types. For user-defined types,\r
+ * we will need a factory method that takes a Java type name.\r
+ *\r
+ * @param JDBCTypeId The JDBC Id of the type, as listed in\r
+ * java.sql.Types\r
+ *\r
+ * @return The appropriate TypeId, or null if there is no such\r
+ * TypeId.\r
+ */\r
+\r
+ public static TypeId getBuiltInTypeId(int JDBCTypeId)\r
+ {\r
+ TypeId ret = null;\r
+\r
+ switch (JDBCTypeId)\r
+ {\r
+ case Types.TINYINT:\r
+ ret = TINYINT_ID;\r
+ if (ret == null)\r
+ ret = TINYINT_ID = new TypeId(StoredFormatIds.TINYINT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.TINYINT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.SMALLINT:\r
+ ret = SMALLINT_ID;\r
+ if (ret == null)\r
+ ret = SMALLINT_ID = new TypeId(StoredFormatIds.SMALLINT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.SMALLINT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.INTEGER:\r
+ return INTEGER_ID;\r
+\r
+ case Types.BIGINT:\r
+ ret = LONGINT_ID;\r
+ if (ret == null)\r
+ ret = LONGINT_ID = new TypeId(StoredFormatIds.LONGINT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.LONGINT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.REAL:\r
+ ret = REAL_ID;\r
+ if (ret == null)\r
+ ret = REAL_ID = new TypeId(StoredFormatIds.REAL_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.REAL_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.FLOAT:\r
+ case Types.DOUBLE:\r
+ ret = DOUBLE_ID;\r
+ if (ret == null)\r
+ ret = DOUBLE_ID = new TypeId(StoredFormatIds.DOUBLE_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.DOUBLE_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.DECIMAL:\r
+ ret = DECIMAL_ID;\r
+ if (ret == null)\r
+ ret = DECIMAL_ID = new TypeId(StoredFormatIds.DECIMAL_TYPE_ID,\r
+ new DecimalTypeIdImpl());\r
+ break;\r
+\r
+ case Types.NUMERIC:\r
+ ret = NUMERIC_ID;\r
+ if (ret == null) {\r
+ DecimalTypeIdImpl numericTypeIdImpl = new DecimalTypeIdImpl();\r
+ numericTypeIdImpl.setNumericType();\r
+ ret = NUMERIC_ID = new TypeId(StoredFormatIds.DECIMAL_TYPE_ID, numericTypeIdImpl);\r
+ }\r
+ break;\r
+\r
+ case Types.CHAR:\r
+ return CHAR_ID;\r
+\r
+ case Types.VARCHAR:\r
+ ret = VARCHAR_ID;\r
+ if (ret == null)\r
+ ret = VARCHAR_ID = new TypeId(StoredFormatIds.VARCHAR_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.VARCHAR_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.DATE:\r
+ ret = DATE_ID;\r
+ if (ret == null)\r
+ ret = DATE_ID = new TypeId(StoredFormatIds.DATE_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.DATE_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.TIME:\r
+ ret = TIME_ID;\r
+ if (ret == null)\r
+ ret = TIME_ID = new TypeId(StoredFormatIds.TIME_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.TIME_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.TIMESTAMP:\r
+ ret = TIMESTAMP_ID;\r
+ if (ret == null)\r
+ ret = TIMESTAMP_ID = new TypeId(StoredFormatIds.TIMESTAMP_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.TIMESTAMP_TYPE_ID_IMPL));\r
+ break;\r
+ case Types.BIT:\r
+ case JDBC30Translation.SQL_TYPES_BOOLEAN:\r
+ return BOOLEAN_ID;\r
+\r
+ case Types.BINARY:\r
+ ret = BIT_ID;\r
+ if (ret == null)\r
+ ret = BIT_ID = new TypeId(StoredFormatIds.BIT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.BIT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.VARBINARY:\r
+ ret = VARBIT_ID;\r
+ if (ret == null)\r
+ ret = VARBIT_ID = new TypeId(StoredFormatIds.VARBIT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.VARBIT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.LONGVARBINARY:\r
+ ret = LONGVARBIT_ID;\r
+ if (ret == null)\r
+ ret = LONGVARBIT_ID = new TypeId(StoredFormatIds.LONGVARBIT_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.LONGVARBIT_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case Types.LONGVARCHAR:\r
+ ret = LONGVARCHAR_ID;\r
+ if (ret == null)\r
+ ret = LONGVARCHAR_ID = new TypeId(StoredFormatIds.LONGVARCHAR_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.LONGVARCHAR_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ case JDBC20Translation.SQL_TYPES_BLOB:\r
+ ret = BLOB_ID;\r
+ if (ret == null)\r
+ ret = BLOB_ID = new TypeId(StoredFormatIds.BLOB_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.BLOB_TYPE_ID_IMPL));\r
+ break;\r
+ \r
+ case JDBC20Translation.SQL_TYPES_CLOB:\r
+ ret = CLOB_ID;\r
+ if (ret == null)\r
+ ret = CLOB_ID = new TypeId(StoredFormatIds.CLOB_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.CLOB_TYPE_ID_IMPL));\r
+ break;\r
+\r
+ // XML is not a JDBC type, so we have to check for our\r
+ // internal XML type.\r
+ case StoredFormatIds.XML_TYPE_ID:\r
+ ret = XML_ID;\r
+ if (ret == null)\r
+ ret = XML_ID = new TypeId(StoredFormatIds.XML_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.XML_TYPE_ID_IMPL));\r
+ break;\r
+ }\r
+ return ret;\r
+ }\r
+\r
+ public static TypeId getUserDefinedTypeId(String className, boolean delimitedIdentifier)\r
+ {\r
+ return new TypeId(StoredFormatIds.USERDEFINED_TYPE_ID_V3,\r
+ new UserDefinedTypeIdImpl(className), delimitedIdentifier\r
+ );\r
+ }\r
+\r
+ /**\r
+ * Get a TypeId for the class that corresponds to the given\r
+ * Java type name.\r
+ *\r
+ * @param javaTypeName The name of the Java type\r
+ *\r
+ * @return A TypeId for the SQL type that corresponds to\r
+ * the Java type, null if there is no corresponding type.\r
+ */\r
+ public static TypeId getSQLTypeForJavaType(String javaTypeName)\r
+ {\r
+ if (javaTypeName.equals("java.lang.Boolean") ||\r
+ javaTypeName.equals("boolean"))\r
+ {\r
+ return TypeId.BOOLEAN_ID;\r
+ }\r
+ else if (javaTypeName.equals("byte[]"))\r
+ {\r
+ return getBuiltInTypeId(Types.VARBINARY);\r
+ }\r
+ else if (javaTypeName.equals("java.lang.String"))\r
+ {\r
+ return getBuiltInTypeId(Types.VARCHAR);\r
+ }\r
+ else if (javaTypeName.equals("java.lang.Integer") ||\r
+ javaTypeName.equals("int"))\r
+ {\r
+ return TypeId.INTEGER_ID;\r
+ }\r
+ else if (javaTypeName.equals("byte"))\r
+ {\r
+ return getBuiltInTypeId(Types.TINYINT);\r
+ }\r
+ else if (javaTypeName.equals("short"))\r
+ {\r
+ return getBuiltInTypeId(Types.SMALLINT);\r
+ }\r
+ else if (javaTypeName.equals("java.lang.Long") ||\r
+ javaTypeName.equals("long"))\r
+ {\r
+ return getBuiltInTypeId(Types.BIGINT);\r
+ }\r
+ else if (javaTypeName.equals("java.lang.Float") ||\r
+ javaTypeName.equals("float"))\r
+ {\r
+ return getBuiltInTypeId(Types.REAL);\r
+ }\r
+ else if (javaTypeName.equals("java.lang.Double") ||\r
+ javaTypeName.equals("double"))\r
+ {\r
+ return getBuiltInTypeId(Types.DOUBLE);\r
+ }\r
+ else if (javaTypeName.equals("java.math.BigDecimal"))\r
+ {\r
+ return getBuiltInTypeId(Types.DECIMAL);\r
+ }\r
+ else if (javaTypeName.equals("java.sql.Date"))\r
+ {\r
+ return getBuiltInTypeId(Types.DATE);\r
+ }\r
+ else if (javaTypeName.equals("java.sql.Time"))\r
+ {\r
+ return getBuiltInTypeId(Types.TIME);\r
+ }\r
+ else if (javaTypeName.equals("java.sql.Timestamp"))\r
+ {\r
+ return getBuiltInTypeId(Types.TIMESTAMP);\r
+ }\r
+ else if (javaTypeName.equals("java.sql.Blob"))\r
+ {\r
+ return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_BLOB);\r
+ }\r
+ else if (javaTypeName.equals("java.sql.Clob"))\r
+ {\r
+ return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);\r
+ }\r
+ else if (javaTypeName.equals("org.apache.derby.iapi.types.XML"))\r
+ {\r
+ return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ ** If it's a Java primitive type, return null to indicate that\r
+ ** there is no corresponding SQL type (all the Java primitive\r
+ ** types that have corresponding SQL types are handled above).\r
+ **\r
+ ** There is only one primitive type not mentioned above, char.\r
+ */\r
+ if (javaTypeName.equals("char"))\r
+ {\r
+ return null;\r
+ }\r
+\r
+ /*\r
+ ** It's a non-primitive type (a class) that does not correspond\r
+ ** to a SQL built-in type, so treat it as a user-defined type.\r
+ */\r
+ return TypeId.getUserDefinedTypeId(javaTypeName, false);\r
+ }\r
+ }\r
+\r
+ public static TypeId getBuiltInTypeId(String SQLTypeName) {\r
+\r
+ if (SQLTypeName.equals(TypeId.BOOLEAN_NAME)) {\r
+ return TypeId.BOOLEAN_ID;\r
+ }\r
+ if (SQLTypeName.equals(TypeId.CHAR_NAME)) {\r
+ return TypeId.CHAR_ID;\r
+ }\r
+ if (SQLTypeName.equals(TypeId.DATE_NAME)) {\r
+ return getBuiltInTypeId(Types.DATE);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.DOUBLE_NAME)) {\r
+ return getBuiltInTypeId(Types.DOUBLE);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.FLOAT_NAME)) {\r
+ return getBuiltInTypeId(Types.DOUBLE);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.INTEGER_NAME)) {\r
+ return TypeId.INTEGER_ID;\r
+ }\r
+ if (SQLTypeName.equals(TypeId.LONGINT_NAME)) {\r
+ return getBuiltInTypeId(Types.BIGINT);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.REAL_NAME)) {\r
+ return getBuiltInTypeId(Types.REAL);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.SMALLINT_NAME)) {\r
+ return getBuiltInTypeId(Types.SMALLINT);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.TIME_NAME)) {\r
+ return getBuiltInTypeId(Types.TIME);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.TIMESTAMP_NAME)) {\r
+ return getBuiltInTypeId(Types.TIMESTAMP);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.VARCHAR_NAME)) {\r
+ return getBuiltInTypeId(Types.VARCHAR);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.BIT_NAME)) {\r
+ return getBuiltInTypeId(Types.BINARY);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.VARBIT_NAME)) {\r
+ return getBuiltInTypeId(Types.VARBINARY);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.TINYINT_NAME)) {\r
+ return getBuiltInTypeId(Types.TINYINT);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.DECIMAL_NAME)) {\r
+ return getBuiltInTypeId(Types.DECIMAL);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.NUMERIC_NAME)) {\r
+ return getBuiltInTypeId(Types.NUMERIC);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.LONGVARCHAR_NAME)) {\r
+ return getBuiltInTypeId(Types.LONGVARCHAR);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.LONGVARBIT_NAME)) {\r
+ return getBuiltInTypeId(Types.LONGVARBINARY);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.BLOB_NAME)) {\r
+ return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_BLOB);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.CLOB_NAME)) {\r
+ return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);\r
+ }\r
+ if (SQLTypeName.equals(TypeId.XML_NAME)) {\r
+ return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);\r
+ }\r
+\r
+ TypeId ret = null;\r
+\r
+ // Types defined below here are SQL types and non-JDBC types that are supported by Derby\r
+ if (SQLTypeName.equals(TypeId.REF_NAME)) {\r
+ ret = REF_ID;\r
+ if (ret == null)\r
+ ret = REF_ID = new TypeId(StoredFormatIds.REF_TYPE_ID,\r
+ new BaseTypeIdImpl(StoredFormatIds.REF_TYPE_ID_IMPL));\r
+ }\r
+ return ret;\r
+ }\r
+\r
+ /*\r
+ ** Instance fields and methods\r
+ */\r
+\r
+ private BaseTypeIdImpl baseTypeId;\r
+ private int formatId;\r
+\r
+ /* Set in setTypeIdSpecificInstanceVariables() as needed */\r
+ private boolean classNameWasDelimitedIdentifier;\r
+ private boolean isBitTypeId;\r
+ private boolean isLOBTypeId;\r
+ private boolean isBooleanTypeId;\r
+ private boolean isConcatableTypeId;\r
+ private boolean isDecimalTypeId;\r
+ private boolean isLongConcatableTypeId;\r
+ private boolean isNumericTypeId;\r
+ private boolean isRefTypeId;\r
+ private boolean isStringTypeId;\r
+ private boolean isFloatingPointTypeId;\r
+ private boolean isRealTypeId;\r
+ private boolean isDateTimeTimeStampTypeId;\r
+ private boolean isUserDefinedTypeId;\r
+ private int maxPrecision;\r
+ private int maxScale;\r
+ private int typePrecedence;\r
+ private String javaTypeName;\r
+ private int maxMaxWidth;\r
+\r
+ /**\r
+ * 1 argmument constructor. Needed for Formatable interface to work.\r
+ *\r
+ * @param formatId Format id of specific type id.\r
+ */\r
+\r
+ public TypeId(int formatId) \r
+ {\r
+ this.formatId = formatId;\r
+ setTypeIdSpecificInstanceVariables();\r
+ }\r
+\r
+ /**\r
+ * Constructor for a TypeId\r
+ *\r
+ * @param formatId Format id of specific type id.\r
+ * @param baseTypeId The Base type id\r
+ */\r
+ public TypeId(int formatId, BaseTypeIdImpl baseTypeId)\r
+ {\r
+ this.formatId = formatId;\r
+ this.baseTypeId = baseTypeId;\r
+ setTypeIdSpecificInstanceVariables();\r
+ }\r
+ /**\r
+ * Constructor for a TypeId for user defined types\r
+ *\r
+ * @param formatId Format id of specific type id.\r
+ * @param baseTypeId The Base type id\r
+ * @param classNameWasDelimitedIdentifier Whether or not the class name\r
+ * was a delimited identifier\r
+ */\r
+ public TypeId(int formatId, BaseTypeIdImpl baseTypeId,\r
+ boolean classNameWasDelimitedIdentifier)\r
+ {\r
+ this.formatId = formatId;\r
+ this.baseTypeId = baseTypeId;\r
+ this.classNameWasDelimitedIdentifier = classNameWasDelimitedIdentifier;\r
+ setTypeIdSpecificInstanceVariables();\r
+ }\r
+\r
+ /**\r
+ * we want equals to say if these are the same type id or not.\r
+ */\r
+ public boolean equals(Object that)\r
+ {\r
+ if (that instanceof TypeId)\r
+ return this.getSQLTypeName().equals(((TypeId)that).getSQLTypeName());\r
+ else\r
+ return false;\r
+ }\r
+\r
+ /*\r
+ Hashcode which works with equals.\r
+ */\r
+ public int hashCode()\r
+ {\r
+ return this.getSQLTypeName().hashCode();\r
+ }\r
+\r
+\r
+ private void setTypeIdSpecificInstanceVariables()\r
+ {\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.BIT_TYPE_ID:\r
+ typePrecedence = BIT_PRECEDENCE;\r
+ javaTypeName = "byte[]";\r
+ maxMaxWidth = TypeId.BIT_MAXWIDTH;\r
+ isBitTypeId = true;\r
+ isConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.BOOLEAN_TYPE_ID:\r
+ typePrecedence = BOOLEAN_PRECEDENCE;\r
+ javaTypeName = "java.lang.Boolean";\r
+ maxMaxWidth = TypeId.BOOLEAN_MAXWIDTH;\r
+ isBooleanTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.CHAR_TYPE_ID:\r
+ typePrecedence = CHAR_PRECEDENCE;\r
+ javaTypeName = "java.lang.String";\r
+ maxMaxWidth = TypeId.CHAR_MAXWIDTH;\r
+ isStringTypeId = true;\r
+ isConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.DATE_TYPE_ID:\r
+ typePrecedence = DATE_PRECEDENCE;\r
+ javaTypeName = "java.sql.Date";\r
+ maxMaxWidth = TypeId.DATE_MAXWIDTH;\r
+ maxPrecision = TypeId.DATE_MAXWIDTH;\r
+ isDateTimeTimeStampTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.DECIMAL_TYPE_ID:\r
+ maxPrecision = TypeId.DECIMAL_PRECISION;\r
+ maxScale = TypeId.DECIMAL_SCALE;\r
+ typePrecedence = DECIMAL_PRECEDENCE;\r
+ javaTypeName = "java.math.BigDecimal";\r
+ maxMaxWidth = TypeId.DECIMAL_MAXWIDTH;\r
+ isDecimalTypeId = true;\r
+ isNumericTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.DOUBLE_TYPE_ID:\r
+ maxPrecision = TypeId.DOUBLE_PRECISION;\r
+ maxScale = TypeId.DOUBLE_SCALE;\r
+ typePrecedence = DOUBLE_PRECEDENCE;\r
+ javaTypeName = "java.lang.Double";\r
+ maxMaxWidth = TypeId.DOUBLE_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ isFloatingPointTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.INT_TYPE_ID:\r
+ maxPrecision = TypeId.INT_PRECISION;\r
+ maxScale = TypeId.INT_SCALE;\r
+ typePrecedence = INT_PRECEDENCE;\r
+ javaTypeName = "java.lang.Integer";\r
+ maxMaxWidth = TypeId.INT_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.LONGINT_TYPE_ID:\r
+ maxPrecision = TypeId.LONGINT_PRECISION;\r
+ maxScale = TypeId.LONGINT_SCALE;\r
+ typePrecedence = LONGINT_PRECEDENCE;\r
+ javaTypeName = "java.lang.Long";\r
+ maxMaxWidth = TypeId.LONGINT_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.LONGVARBIT_TYPE_ID:\r
+ typePrecedence = LONGVARBIT_PRECEDENCE;\r
+ javaTypeName = "byte[]";\r
+ maxMaxWidth = TypeId.LONGVARBIT_MAXWIDTH;\r
+ isBitTypeId = true;\r
+ isConcatableTypeId = true;\r
+ isLongConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.LONGVARCHAR_TYPE_ID:\r
+ typePrecedence = LONGVARCHAR_PRECEDENCE;\r
+ javaTypeName = "java.lang.String";\r
+ maxMaxWidth = TypeId.LONGVARCHAR_MAXWIDTH;\r
+ isStringTypeId = true;\r
+ isConcatableTypeId = true;\r
+ isLongConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.REAL_TYPE_ID:\r
+ maxPrecision = TypeId.REAL_PRECISION;\r
+ maxScale = TypeId.REAL_SCALE;\r
+ typePrecedence = REAL_PRECEDENCE;\r
+ javaTypeName = "java.lang.Float";\r
+ maxMaxWidth = TypeId.REAL_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ isRealTypeId = true;\r
+ isFloatingPointTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.REF_TYPE_ID:\r
+ typePrecedence = REF_PRECEDENCE;\r
+ isRefTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.SMALLINT_TYPE_ID:\r
+ maxPrecision = TypeId.SMALLINT_PRECISION;\r
+ maxScale = TypeId.SMALLINT_SCALE;\r
+ typePrecedence = SMALLINT_PRECEDENCE;\r
+ javaTypeName = "java.lang.Integer";\r
+ maxMaxWidth = TypeId.SMALLINT_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.TIME_TYPE_ID:\r
+ typePrecedence = TIME_PRECEDENCE;\r
+ javaTypeName = "java.sql.Time";\r
+ maxScale = TypeId.TIME_SCALE;\r
+ maxMaxWidth = TypeId.TIME_MAXWIDTH;\r
+ maxPrecision = TypeId.TIME_MAXWIDTH;\r
+ isDateTimeTimeStampTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.TIMESTAMP_TYPE_ID:\r
+ typePrecedence = TIMESTAMP_PRECEDENCE;\r
+ javaTypeName = "java.sql.Timestamp";\r
+ maxScale = TypeId.TIMESTAMP_SCALE;\r
+ maxMaxWidth = TypeId.TIMESTAMP_MAXWIDTH;\r
+ maxPrecision = TypeId.TIMESTAMP_MAXWIDTH;\r
+ isDateTimeTimeStampTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.TINYINT_TYPE_ID:\r
+ maxPrecision = TypeId.TINYINT_PRECISION;\r
+ maxScale = TypeId.TINYINT_SCALE;\r
+ typePrecedence = TINYINT_PRECEDENCE;\r
+ javaTypeName = "java.lang.Integer";\r
+ maxMaxWidth = TypeId.TINYINT_MAXWIDTH;\r
+ isNumericTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ if (baseTypeId != null)\r
+ {\r
+ setUserTypeIdInfo();\r
+ }\r
+ else\r
+ {\r
+ typePrecedence = USER_PRECEDENCE;\r
+ }\r
+ maxMaxWidth = -1;\r
+ isUserDefinedTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.VARBIT_TYPE_ID:\r
+ typePrecedence = VARBIT_PRECEDENCE;\r
+ javaTypeName = "byte[]";\r
+ maxMaxWidth = TypeId.VARBIT_MAXWIDTH;\r
+ isBitTypeId = true;\r
+ isConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.BLOB_TYPE_ID:\r
+ typePrecedence = BLOB_PRECEDENCE;\r
+ javaTypeName = "java.sql.Blob";\r
+ maxMaxWidth = TypeId.BLOB_MAXWIDTH;\r
+ isBitTypeId = true;\r
+ isConcatableTypeId = true;\r
+ isLongConcatableTypeId = true; // ??\r
+ isLOBTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.VARCHAR_TYPE_ID:\r
+ typePrecedence = VARCHAR_PRECEDENCE;\r
+ javaTypeName = "java.lang.String";\r
+ maxMaxWidth = TypeId.VARCHAR_MAXWIDTH;\r
+ isStringTypeId = true;\r
+ isConcatableTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.CLOB_TYPE_ID:\r
+ typePrecedence = CLOB_PRECEDENCE;\r
+ javaTypeName = "java.sql.Clob";\r
+ maxMaxWidth = TypeId.CLOB_MAXWIDTH;\r
+ isStringTypeId = true;\r
+ isConcatableTypeId = true;\r
+ isLongConcatableTypeId = true; // ??\r
+ isLOBTypeId = true;\r
+ break;\r
+\r
+ case StoredFormatIds.XML_TYPE_ID:\r
+\r
+ typePrecedence = XML_PRECEDENCE;\r
+ javaTypeName = "org.apache.derby.iapi.types.XML";\r
+ maxMaxWidth = TypeId.XML_MAXWIDTH;\r
+\r
+ // We set this to true in order to disallow use\r
+ // of the XML datatype for procedure/function args.\r
+ isLongConcatableTypeId = true;\r
+ break;\r
+\r
+ }\r
+ }\r
+ /**\r
+ * JDBC has its own idea of type identifiers which is different from\r
+ * the Derby internal type ids. The JDBC type ids are defined\r
+ * as public final static ints in java.sql.Types. This method translates\r
+ * a Derby internal TypeId to a JDBC type id. For java objects this\r
+ * returns JAVA_OBJECT in Java2 and OTHER in JDK 1.1. For Boolean datatypes,\r
+ * this returns Type.BOOLEAN in JDK1.4 and Type.BIT for jdks prior to 1.4\r
+ *\r
+ * @return The JDBC type Id for this type\r
+ */\r
+ public final int getJDBCTypeId()\r
+ {\r
+ return baseTypeId.getJDBCTypeId();\r
+ }\r
+ /**\r
+ * Returns the SQL name of the datatype. If it is a user-defined type,\r
+ * it returns the full Java path name for the datatype, meaning the\r
+ * dot-separated path including the package names.\r
+ *\r
+ * @return A String containing the SQL name of this type.\r
+ */\r
+ public String getSQLTypeName()\r
+ {\r
+ return baseTypeId.getSQLTypeName();\r
+ }\r
+\r
+ /**\r
+ * Tell whether this is a built-in type.\r
+ * NOTE: There are 3 "classes" of types:\r
+ * built-in - system provided types which are implemented internally\r
+ * (int, smallint, etc.)\r
+ * system built-in - system provided types, independent of implementation\r
+ * (date, time, etc.)\r
+ * user types - types implemented outside of the system\r
+ * (java.lang.Integer, asdf.asdf.asdf, etc.)\r
+ *\r
+ * @return true for built-in types, false for user-defined types.\r
+ */\r
+ public final boolean userType()\r
+ {\r
+ return baseTypeId.userType();\r
+ }\r
+\r
+ /**\r
+ * Get the maximum precision of the type. For types with variable\r
+ * precision, this is an arbitrary high precision.\r
+ *\r
+ * @return The maximum precision of the type\r
+ */\r
+ public int getMaximumPrecision()\r
+ {\r
+ return maxPrecision;\r
+ }\r
+\r
+ /**\r
+ * Get the maximum scale of the type. For types with variable scale,\r
+ * this is an arbitrary high scale.\r
+ *\r
+ * @return The maximum scale of the type\r
+ */\r
+ public int getMaximumScale()\r
+ {\r
+ return maxScale;\r
+ }\r
+\r
+ /**\r
+ * Set the nested BaseTypeId in this TypeId.\r
+ */\r
+ public void setNestedTypeId(BaseTypeIdImpl typeId)\r
+ {\r
+ baseTypeId = typeId;\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ setUserTypeIdInfo();\r
+ }\r
+ }\r
+\r
+ private void setUserTypeIdInfo()\r
+ {\r
+ UserDefinedTypeIdImpl baseUserTypeId =\r
+ (UserDefinedTypeIdImpl) baseTypeId;\r
+ typePrecedence = USER_PRECEDENCE;\r
+ javaTypeName = baseUserTypeId.getClassName();\r
+ }\r
+\r
+ /**\r
+ * For user types, tell whether or not the class name was a\r
+ * delimited identifier. For all other types, return false.\r
+ *\r
+ * @return Whether or not the class name was a delimited identifier.\r
+ */\r
+ public boolean getClassNameWasDelimitedIdentifier()\r
+ {\r
+ return classNameWasDelimitedIdentifier;\r
+ }\r
+\r
+ /**\r
+ * Does this TypeId represent a TypeId for a StringDataType.\r
+ *\r
+ * @return Whether or not this TypeId represents a TypeId for a StringDataType.\r
+ */\r
+ public boolean isStringTypeId()\r
+ {\r
+ return isStringTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a TypeId for DATE/TIME/TIMESTAMP\r
+ *\r
+ * @return true if this is a DATE/TIME/TIMESTAMP\r
+ */\r
+ public boolean isDateTimeTimeStampTypeId()\r
+ {\r
+ return isDateTimeTimeStampTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a TypeId for REAL\r
+ *\r
+ * @return true if this is a REAL\r
+ */\r
+ public boolean isRealTypeId()\r
+ {\r
+ return isRealTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a TypeId for floating point (REAL/DOUBLE)\r
+ *\r
+ * @return true if this is a REAL or DOUBLE\r
+ */\r
+ public boolean isFloatingPointTypeId()\r
+ {\r
+ return isFloatingPointTypeId;\r
+ }\r
+ \r
+ /**\r
+ * Is this a TypeId for DOUBLE\r
+ *\r
+ * @return true if this is a DOUBLE\r
+ */\r
+ public boolean isDoubleTypeId()\r
+ {\r
+ return isFloatingPointTypeId && (! isRealTypeId);\r
+ }\r
+ \r
+ /**\r
+ * Is this a fixed string type?\r
+ * @return true if this is CHAR\r
+ */\r
+ public boolean isFixedStringTypeId()\r
+ {\r
+ return (formatId == StoredFormatIds.CHAR_TYPE_ID);\r
+ }\r
+\r
+ /** \r
+ *Is this a Clob?\r
+ * @return true if this is CLOB\r
+ */\r
+ public boolean isClobTypeId()\r
+ {\r
+ return (formatId == StoredFormatIds.CLOB_TYPE_ID);\r
+ }\r
+\r
+ /** \r
+ *Is this a Blob?\r
+ * @return true if this is BLOB\r
+ */\r
+ public boolean isBlobTypeId()\r
+ {\r
+ return ((formatId == StoredFormatIds.BLOB_TYPE_ID));\r
+ }\r
+\r
+ \r
+ /** \r
+ *Is this a LongVarchar?\r
+ * @return true if this is LongVarchar\r
+ */\r
+ public boolean isLongVarcharTypeId()\r
+ {\r
+ return (formatId == StoredFormatIds.LONGVARCHAR_TYPE_ID);\r
+ }\r
+\r
+\r
+ /** \r
+ * Is this DATE/TIME or TIMESTAMP?\r
+ *\r
+ * @return true if this DATE/TIME or TIMESTAMP\r
+ */\r
+ public boolean isDateTimeTimeStampTypeID()\r
+ {\r
+ return ((formatId == StoredFormatIds.DATE_TYPE_ID) ||\r
+ (formatId == StoredFormatIds.TIME_TYPE_ID) ||\r
+ (formatId == StoredFormatIds.TIMESTAMP_TYPE_ID));\r
+ }\r
+\r
+ /** \r
+ *Is this an XML doc?\r
+ * @return true if this is XML\r
+ */\r
+ public boolean isXMLTypeId()\r
+ {\r
+ return (formatId == StoredFormatIds.XML_TYPE_ID);\r
+ }\r
+\r
+ /**\r
+ * Tell whether this type is orderable, that is, can participate\r
+ * in comparisons.\r
+ *\r
+ * @param cf A ClassFactory\r
+ *\r
+ * @return true for orderable types, false for non-orderable types.\r
+ */\r
+ public boolean orderable(ClassFactory cf)\r
+ {\r
+ boolean orderable;\r
+ switch (formatId)\r
+ {\r
+ // cmp not allowed, indexing not allowed\r
+ case StoredFormatIds.BLOB_TYPE_ID:\r
+ case StoredFormatIds.CLOB_TYPE_ID:\r
+ case StoredFormatIds.LONGVARCHAR_TYPE_ID:\r
+ case StoredFormatIds.XML_TYPE_ID:\r
+ case StoredFormatIds.LONGVARBIT_TYPE_ID:\r
+ return false;\r
+\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ /* Is this type orderable? */\r
+\r
+ // For user java classes we are orderable if we\r
+ // implement java.lang.Orderable (JDK1.2) or\r
+ // have a int compareTo(Object) method (JDK1.1 or JDK1.2)\r
+ UserDefinedTypeIdImpl baseUserTypeId =\r
+ (UserDefinedTypeIdImpl) baseTypeId;\r
+\r
+ String className = baseUserTypeId.getClassName();\r
+\r
+ try \r
+ {\r
+ Class c = cf.getClassInspector().getClass(className);\r
+ orderable = java.lang.Comparable.class.isAssignableFrom(c);\r
+ } \r
+ catch (ClassNotFoundException cnfe) \r
+ {\r
+ orderable = false;\r
+ } \r
+ break;\r
+\r
+ default:\r
+ orderable = true;\r
+ }\r
+\r
+ return orderable;\r
+ }\r
+\r
+ /**\r
+ * Each built-in type in JSQL has a precedence. This precedence determines\r
+ * how to do type promotion when using binary operators. For example, float\r
+ * has a higher precedence than int, so when adding an int to a float, the\r
+ * result type is float.\r
+ *\r
+ * The precedence for some types is arbitrary. For example, it doesn't\r
+ * matter what the precedence of the boolean type is, since it can't be\r
+ * mixed with other types. But the precedence for the number types is\r
+ * critical. The SQL standard requires that exact numeric types be\r
+ * promoted to approximate numeric when one operator uses both. Also,\r
+ * the precedence is arranged so that one will not lose precision when\r
+ * promoting a type.\r
+ * NOTE: char, varchar, and longvarchar must appear at the bottom of\r
+ * the hierarchy, but above USER_PRECEDENCE, since we allow the implicit\r
+ * conversion of those types to any other built-in system type.\r
+ *\r
+ * @return The precedence of this type.\r
+ */\r
+ public int typePrecedence()\r
+ {\r
+ return typePrecedence;\r
+ }\r
+\r
+ /**\r
+ * Get the name of the corresponding Java type.\r
+ *\r
+ * Each SQL type has a corresponding Java type. When a SQL value is\r
+ * passed to a Java method, it is translated to its corresponding Java\r
+ * type. For example, when a SQL date column is passed to a method,\r
+ * it is translated to a java.sql.Date.\r
+ *\r
+ * @return The name of the corresponding Java type.\r
+ */\r
+ public String getCorrespondingJavaTypeName()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (formatId == StoredFormatIds.REF_TYPE_ID)\r
+ {\r
+ SanityManager.THROWASSERT("getCorrespondingJavaTypeName not implemented for StoredFormatIds.REF_TYPE_ID");\r
+ }\r
+ SanityManager.ASSERT(javaTypeName != null,\r
+ "javaTypeName expected to be non-null");\r
+ }\r
+ return javaTypeName;\r
+ }\r
+\r
+ /**\r
+ * Get the name of the corresponding Java type.\r
+ *\r
+ * This method is used directly from EmbedResultSetMetaData (jdbc)\r
+ * to return the corresponding type (as choosen by getObject).\r
+ * It solves a specific problem for BLOB types where the \r
+ * getCorrespondingJavaTypeName() is used internall for casting\r
+ * which doesn't work if changed from byte[] to java.sql.Blob.\r
+ * So we do it here instread, to avoid unexpected sideeffects.\r
+ *\r
+ * @return The name of the corresponding Java type.\r
+ */\r
+ public String getResultSetMetaDataTypeName()\r
+ {\r
+ if ((BLOB_ID != null) && BLOB_ID.equals(this))\r
+ return "java.sql.Blob";\r
+ if ((CLOB_ID != null) && CLOB_ID.equals(this))\r
+ return "java.sql.Clob";\r
+ return getCorrespondingJavaTypeName();\r
+ }\r
+\r
+ /**\r
+ * Get the maximum maximum width of the type (that's not a typo). For\r
+ * types with variable length, this is the absolute maximum for the type.\r
+ *\r
+ * @return The maximum maximum width of the type\r
+ */\r
+ public int getMaximumMaximumWidth()\r
+ {\r
+ return maxMaxWidth;\r
+ }\r
+\r
+ /**\r
+ * Converts this TypeId, given a data type descriptor (including length/precision),\r
+ * to a string. E.g.\r
+ *\r
+ * VARCHAR(30)\r
+ *\r
+ *\r
+ * For most data types, we just return the SQL type name.\r
+ *\r
+ * @param dts Data type descriptor that holds the length/precision etc. as necessary\r
+ *\r
+ * @return String version of datatype, suitable for running through\r
+ * the Parser.\r
+ */\r
+ public String toParsableString(DataTypeDescriptor dts)\r
+ {\r
+ return baseTypeId.toParsableString(dts);\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a numeric type?\r
+ *\r
+ * @return Whether or not this a type id for a numeric type.\r
+ */\r
+ public boolean isNumericTypeId()\r
+ {\r
+ return isNumericTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a decimal type?\r
+ *\r
+ * @return Whether or not this a type id for a decimal type.\r
+ */\r
+ public boolean isDecimalTypeId()\r
+ {\r
+ return isDecimalTypeId;\r
+ }\r
+\r
+\r
+ /**\r
+ * Is this a type id for a boolean type?\r
+ *\r
+ * @return Whether or not this a type id for a boolean type.\r
+ */\r
+ public boolean isBooleanTypeId()\r
+ {\r
+ return isBooleanTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a ref type?\r
+ *\r
+ * @return Whether or not this a type id for a ref type.\r
+ */\r
+ public boolean isRefTypeId()\r
+ {\r
+ return isRefTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a concatable type?\r
+ *\r
+ * @return Whether or not this a type id for a concatable type.\r
+ */\r
+ public boolean isConcatableTypeId()\r
+ {\r
+ return isConcatableTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a bit type?\r
+ *\r
+ * @return Whether or not this a type id for a bit type.\r
+ */\r
+ public boolean isBitTypeId()\r
+ {\r
+ return isBitTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a LOB type?\r
+ *\r
+ * @return Whether or not this a type id for a LOB type.\r
+ */\r
+ public boolean isLOBTypeId()\r
+ {\r
+ return isLOBTypeId;\r
+ }\r
+\r
+\r
+ /**\r
+ * Is this a type id for a long concatable type?\r
+ *\r
+ * @return Whether or not this a type id for a long concatable type.\r
+ */\r
+ public boolean isLongConcatableTypeId()\r
+ {\r
+ return isLongConcatableTypeId;\r
+ }\r
+\r
+ /**\r
+ * Is this a type id for a user defined type?\r
+ *\r
+ * @return Whether or not this a type id for a user defined type.\r
+ */\r
+ public boolean isUserDefinedTypeId()\r
+ {\r
+ return isUserDefinedTypeId;\r
+ }\r
+\r
+ // Formatable interface\r
+\r
+ /**\r
+ * Read this object from a stream of stored objects.\r
+ *\r
+ * @param in read this.\r
+ *\r
+ * @exception IOException thrown on error\r
+ * @exception ClassNotFoundException thrown on error\r
+ */\r
+ public void readExternal( ObjectInput in )\r
+ throws IOException, ClassNotFoundException\r
+ {\r
+ baseTypeId = (BaseTypeIdImpl) in.readObject();\r
+ /* We need to set the type specific variables\r
+ * for user types when reading back off of the\r
+ * disk becuse the baseTypeId was null when the\r
+ * 0 argument constructor was called.\r
+ */\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ setTypeIdSpecificInstanceVariables();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Write this object to a stream of stored objects.\r
+ *\r
+ * @param out write bytes here.\r
+ *\r
+ * @exception IOException thrown on error\r
+ */\r
+ public void writeExternal( ObjectOutput out )\r
+ throws IOException\r
+ {\r
+ out.writeObject( baseTypeId );\r
+ }\r
+\r
+ /**\r
+ * Get the formatID which corresponds to this class.\r
+ *\r
+ * @return the formatID of this class\r
+ */\r
+ public int getTypeFormatId() \r
+ { \r
+ return formatId; \r
+ }\r
+\r
+\r
+ /** \r
+ * Get SQL null value.\r
+ * @return SQL null value for this type.\r
+ */\r
+ public DataValueDescriptor getNull()\r
+ {\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.BIT_TYPE_ID:\r
+ return new SQLBit();\r
+\r
+ case StoredFormatIds.BOOLEAN_TYPE_ID:\r
+ return new SQLBoolean();\r
+\r
+ case StoredFormatIds.CHAR_TYPE_ID:\r
+ return new SQLChar();\r
+\r
+ // Implementation of DECIMAL can change.\r
+ case StoredFormatIds.DECIMAL_TYPE_ID:\r
+ return decimalImplementation.getNewNull();\r
+\r
+ case StoredFormatIds.DOUBLE_TYPE_ID:\r
+ return new SQLDouble();\r
+\r
+ case StoredFormatIds.INT_TYPE_ID:\r
+ return new SQLInteger();\r
+\r
+ case StoredFormatIds.LONGINT_TYPE_ID:\r
+ return new SQLLongint();\r
+\r
+ case StoredFormatIds.LONGVARBIT_TYPE_ID:\r
+ return new SQLLongVarbit();\r
+\r
+ case StoredFormatIds.BLOB_TYPE_ID:\r
+ return new SQLBlob();\r
+\r
+ case StoredFormatIds.CLOB_TYPE_ID:\r
+ return new SQLClob();\r
+\r
+ case StoredFormatIds.LONGVARCHAR_TYPE_ID:\r
+ return new SQLLongvarchar();\r
+\r
+ case StoredFormatIds.REAL_TYPE_ID:\r
+ return new SQLReal();\r
+\r
+ case StoredFormatIds.REF_TYPE_ID:\r
+ return new SQLRef();\r
+\r
+ case StoredFormatIds.SMALLINT_TYPE_ID:\r
+ return new SQLSmallint();\r
+\r
+ case StoredFormatIds.TINYINT_TYPE_ID:\r
+ return new SQLTinyint();\r
+\r
+ case StoredFormatIds.DATE_TYPE_ID:\r
+ return new SQLDate();\r
+\r
+ case StoredFormatIds.TIME_TYPE_ID:\r
+ return new SQLTime();\r
+\r
+ case StoredFormatIds.TIMESTAMP_TYPE_ID:\r
+ return new SQLTimestamp();\r
+\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ return new UserType();\r
+\r
+ case StoredFormatIds.VARBIT_TYPE_ID:\r
+ return new SQLVarbit();\r
+\r
+ case StoredFormatIds.VARCHAR_TYPE_ID:\r
+ return new SQLVarchar();\r
+\r
+ case StoredFormatIds.XML_TYPE_ID:\r
+ return new XML();\r
+\r
+ default:\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.THROWASSERT(\r
+ "unexpected formatId in getNull() - " + formatId);\r
+ }\r
+ return null;\r
+ }\r
+ }\r
+ /**\r
+ * Is this type StreamStorable?\r
+ *\r
+ * @return true if this type has variable length.\r
+ */\r
+ public boolean streamStorable() {\r
+ return isStringTypeId() || isBitTypeId();\r
+ }\r
+\r
+\r
+ //\r
+ // Class methods\r
+ //\r
+\r
+ /**\r
+ * Get the approximate length of this type in bytes.\r
+ * For most datatypes this is just going to be\r
+ * dts.getMaximumWidth(). Some types, such as\r
+ * bit, will override this.\r
+ *\r
+ * @param dts Data type descriptor that holds the \r
+ * length/precision etc. as necessary\r
+ *\r
+ * @return the length in bytes\r
+ */\r
+ public int getApproximateLengthInBytes(DataTypeDescriptor dts)\r
+ {\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.BIT_TYPE_ID:\r
+ return (int)(Math.ceil(dts.getMaximumWidth()/8d));\r
+\r
+ case StoredFormatIds.CHAR_TYPE_ID:\r
+ return (2 * dts.getMaximumWidth()) + 2;\r
+\r
+ case StoredFormatIds.DECIMAL_TYPE_ID:\r
+ // Return 200 if precision is max int\r
+ if (dts.getPrecision() == Integer.MAX_VALUE)\r
+ {\r
+ return 200;\r
+ }\r
+ else\r
+ {\r
+ return 8 + (int) (Math.ceil(((double)dts.getPrecision())/2d));\r
+ }\r
+\r
+ case StoredFormatIds.LONGVARBIT_TYPE_ID:\r
+ case StoredFormatIds.BLOB_TYPE_ID:\r
+ case StoredFormatIds.CLOB_TYPE_ID:\r
+ // RESOLVE: Should XML be here? What's this value mean, anyway?\r
+ case StoredFormatIds.XML_TYPE_ID:\r
+ return 10240;\r
+\r
+ case StoredFormatIds.REF_TYPE_ID:\r
+ return 16;\r
+\r
+ case StoredFormatIds.USERDEFINED_TYPE_ID_V3:\r
+ /* For user types we'll guess on the high side\r
+ ** (200) to avoid being too low in most cases.\r
+ */\r
+ return 200;\r
+\r
+ case StoredFormatIds.VARBIT_TYPE_ID:\r
+ // Return 200 if maximum width is max int\r
+ if (dts.getMaximumWidth() == Integer.MAX_VALUE)\r
+ {\r
+ return 200;\r
+ }\r
+ else\r
+ {\r
+ return (int)(Math.ceil(dts.getMaximumWidth()/8d));\r
+ }\r
+\r
+ case StoredFormatIds.VARCHAR_TYPE_ID:\r
+ case StoredFormatIds.LONGVARCHAR_TYPE_ID:\r
+ // Return 200 if maximum width is max int\r
+ if (dts.getMaximumWidth() == Integer.MAX_VALUE)\r
+ {\r
+ return 200;\r
+ }\r
+ else\r
+ {\r
+ return (dts.getMaximumWidth() * 2) + 2;\r
+ }\r
+ /*\r
+ ** For Date/time we know the exact size\r
+ ** thanks to some investigative work by\r
+ ** someone or other (sad isn't it). \r
+ */\r
+ case StoredFormatIds.DATE_TYPE_ID:\r
+ return 18;\r
+ case StoredFormatIds.TIME_TYPE_ID:\r
+ return 16;\r
+ case StoredFormatIds.TIMESTAMP_TYPE_ID:\r
+ return 29;\r
+\r
+ default:\r
+ return dts.getMaximumWidth();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the base type id that is embedded in this type id. The base type\r
+ * id is an object with a minimal implementation of TypeId that is intended\r
+ * to be usable on the client side.\r
+ */\r
+ public BaseTypeIdImpl getBaseTypeId()\r
+ {\r
+ return baseTypeId;\r
+ }\r
+\r
+ /**\r
+ * Get the precision of the merge of two Decimals\r
+ *\r
+ * @param leftType the left type\r
+ * @param rightType the left type\r
+ *\r
+ * @return the resultant precision\r
+ */\r
+ public int getPrecision(DataTypeDescriptor leftType,\r
+ DataTypeDescriptor rightType)\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (formatId != StoredFormatIds.DECIMAL_TYPE_ID)\r
+ {\r
+ SanityManager.THROWASSERT(\r
+ "getPrecision() not expected to be called for formatId - " + formatId);\r
+ }\r
+ }\r
+ long lscale = (long)leftType.getScale();\r
+ long rscale = (long)rightType.getScale();\r
+ long lprec = (long)leftType.getPrecision();\r
+ long rprec = (long)rightType.getPrecision();\r
+ long val;\r
+\r
+ /*\r
+ ** Take the maximum left of decimal digits plus the scale.\r
+ */\r
+ val = this.getScale(leftType, rightType) +\r
+ Math.max(lprec - lscale, rprec - rscale);\r
+\r
+ if (val > Integer.MAX_VALUE)\r
+ {\r
+ val = Integer.MAX_VALUE;\r
+ }\r
+ return (int)val;\r
+ }\r
+\r
+ /**\r
+ * Get the scale of the merge of two decimals\r
+ *\r
+ * @param leftType the left type\r
+ * @param rightType the left type\r
+ *\r
+ * @return the resultant precision\r
+ */\r
+ public int getScale(DataTypeDescriptor leftType,\r
+ DataTypeDescriptor rightType)\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (formatId != StoredFormatIds.DECIMAL_TYPE_ID)\r
+ {\r
+ SanityManager.THROWASSERT(\r
+ "getPrecision() not expected to be called for formatId - " + formatId);\r
+ }\r
+ }\r
+ /*\r
+ ** Retain greatest scale\r
+ */\r
+ return Math.max(leftType.getScale(), rightType.getScale());\r
+ }\r
+\r
+ /**\r
+ * Does type hava a declared variable length (defined by the application).\r
+ * Examples are CHAR(10), CLOB(1M).\r
+ * Unbounded long types, like LONG VARCHAR return false here.\r
+ * @return boolean true if type is variable length false if not. \r
+ */\r
+ public boolean variableLength()\r
+ {\r
+ switch (formatId)\r
+ {\r
+ case StoredFormatIds.BIT_TYPE_ID:\r
+ case StoredFormatIds.VARBIT_TYPE_ID:\r
+ case StoredFormatIds.DECIMAL_TYPE_ID:\r
+ case StoredFormatIds.CHAR_TYPE_ID:\r
+ case StoredFormatIds.VARCHAR_TYPE_ID:\r
+ case StoredFormatIds.BLOB_TYPE_ID:\r
+ case StoredFormatIds.CLOB_TYPE_ID:\r
+ return true;\r
+\r
+ default:\r
+ return false;\r
+ }\r
+ }\r
+}\r
+\r