/* * Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software;Designed and Developed mainly by many Chinese * opensource volunteers. you can redistribute it and/or modify it under the * terms of the GNU General Public License version 2 only, as published by the * Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Any questions about this component can be directed to it's project Web address * https://code.google.com/p/opencloudb/. * */ package com.akiban.sql.types; import com.akiban.sql.StandardException; import java.sql.Types; /** * TypeId describes the static information about a SQL type * independent of any specific attributes of the type such * as length. So the TypeId for CHARACTER describes the * fundamental information about CHARACTER. A specific * type (e.g. CHARACTER(10)) is described by a TypeDescriptor for * a catlog type and a DataTypeDescriptor for a runtime type. * (note a DataTypeDescriptor adds runtime attributes to the * TypeDescriptor it has). * <P> * A TypeId is immutable. <P> * The equals(Object) method can be used to determine if two typeIds are for the same type, * which defines type id equality. @see DataTypeDescriptor */ public class TypeId { /** * Various fixed numbers related to datatypes. */ public static final int LONGINT_PRECISION = 19; public static final int LONGINT_SCALE = 0; public static final int LONGINT_MAXWIDTH = 20; public static final int INT_PRECISION = 10; public static final int INT_SCALE = 0; public static final int INT_MAXWIDTH = 11; public static final int SMALLINT_PRECISION = 5; public static final int SMALLINT_SCALE = 0; public static final int SMALLINT_MAXWIDTH = 6; public static final int TINYINT_PRECISION = 3; public static final int TINYINT_SCALE = 0; public static final int TINYINT_MAXWIDTH = 4; // precision in number of bits public static final int DOUBLE_PRECISION = 52; // the ResultSetMetaData needs to have the precision for numeric data // in decimal digits, rather than number of bits, so need a separate constant. public static final int DOUBLE_PRECISION_IN_DIGITS = 15; public static final int DOUBLE_SCALE = 0; public static final int DOUBLE_MAXWIDTH = 17; // precision in number of bits public static final int REAL_PRECISION = 23; // the ResultSetMetaData needs to have the precision for numeric data // in decimal digits, rather than number of bits, so need a separate constant. public static final int REAL_PRECISION_IN_DIGITS = 7; public static final int REAL_SCALE = 0; public static final int REAL_MAXWIDTH = 9; public static final int DECIMAL_PRECISION = 31; public static final int DECIMAL_SCALE = 31; public static final int DECIMAL_MAXWIDTH = 31; // TODO: Is there a better place for these? public static final int DEFAULT_DECIMAL_PRECISION = 5; public static final int DEFAULT_DECIMAL_SCALE = 0; public static final int BOOLEAN_MAXWIDTH = 5; // false public static final int CHAR_MAXWIDTH = 254; public static final int VARCHAR_MAXWIDTH = 32672; public static final int LONGVARCHAR_MAXWIDTH = 32700; public static final int BIT_MAXWIDTH = 254; public static final int VARBIT_MAXWIDTH = 32672; public static final int LONGVARBIT_MAXWIDTH = 32700; // not supposed to be limited! 4096G should be ok(?), if Derby can handle... public static final int BLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long public static final int CLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long public static final int XML_MAXWIDTH = Integer.MAX_VALUE; // Max width for datetime values is the length of the // string returned from a call to "toString()" on the // java.sql.Date, java.sql.Time, and java.sql.Timestamp // classes (the result of toString() on those classes // is defined by the JDBC API). This value is also // used as the "precision" for those types. public static final int DATE_MAXWIDTH = 10; // yyyy-mm-dd public static final int TIME_MAXWIDTH = 8; // hh:mm:ss // The format of java.sql.Timestamp.toString() // is yyyy-mm-dd hh:mm:ss.fffffffff public static final int TIMESTAMP_MAXWIDTH = 29; // yyyy-mm-dd hh:mm:ss.fffffffff // Scale DOES exist for time values. For a TIMESTAMP value, // it's 9 ('fffffffff'); for a TIME value, it's 0 (because there // are no fractional seconds). Note that date values do // not have a scale. public static final int TIME_SCALE = 0; public static final int TIMESTAMP_SCALE = 9; public static final int INTERVAL_YEAR_MONTH_PRECISION = 8; public static final int INTERVAL_YEAR_MONTH_SCALE = 0; public static final int INTERVAL_YEAR_MONTH_MAXWIDTH = 11; // yyyyyyyy-mm public static final int INTERVAL_DAY_SECOND_PRECISION = 8; public static final int INTERVAL_DAY_SECOND_SCALE = 6; public static final int INTERVAL_DAY_SECOND_MAXWIDTH = 24; // dddddddd hh:mm:ss.uuuuuu /* These define all the type names for SQL92 and JDBC * NOTE: boolean is SQL3 */ //public static final String BIT_NAME = "BIT"; //public static final String VARBIT_NAME = "BIT VARYING"; //public static final String LONGVARBIT_NAME = "LONG BIT VARYING"; public static final String BIT_NAME = "CHAR () FOR BIT DATA"; public static final String VARBIT_NAME = "VARCHAR () FOR BIT DATA"; public static final String LONGVARBIT_NAME = "LONG VARCHAR FOR BIT DATA"; public static final String TINYINT_NAME = "TINYINT"; public static final String SMALLINT_NAME = "SMALLINT"; public static final String MEDIUMINT_NAME = "MEDIUMINT"; public static final String INTEGER_NAME = "INTEGER"; public static final String INT_NAME = "INT"; public static final String LONGINT_NAME = "BIGINT"; public static final String FLOAT_NAME = "FLOAT"; public static final String REAL_NAME = "REAL"; public static final String DOUBLE_NAME = "DOUBLE"; public static final String NUMERIC_NAME = "NUMERIC"; public static final String DECIMAL_NAME = "DECIMAL"; public static final String CHAR_NAME = "CHAR"; public static final String VARCHAR_NAME = "VARCHAR"; public static final String LONGVARCHAR_NAME = "LONG VARCHAR"; public static final String DATE_NAME = "DATE"; public static final String TIME_NAME = "TIME"; public static final String TIMESTAMP_NAME = "TIMESTAMP"; public static final String BINARY_NAME = "BINARY"; public static final String VARBINARY_NAME = "VARBINARY"; public static final String LONGVARBINARY_NAME = "LONGVARBINARY"; public static final String BOOLEAN_NAME = "BOOLEAN"; public static final String REF_NAME = "REF"; public static final String NATIONAL_CHAR_NAME = "NATIONAL CHAR"; public static final String NATIONAL_VARCHAR_NAME = "NATIONAL CHAR VARYING"; public static final String NATIONAL_LONGVARCHAR_NAME = "LONG NVARCHAR"; public static final String BLOB_NAME = "BLOB"; public static final String CLOB_NAME = "CLOB"; public static final String NCLOB_NAME = "NCLOB"; public static final String TEXT_NAME = "TEXT"; public static final String TINYBLOB_NAME = "TINYBLOB"; public static final String TINYTEXT_NAME = "TINYTEXT"; public static final String MEDIUMBLOB_NAME = "MEDIUMBLOB"; public static final String MEDIUMTEXT_NAME = "MEDIUMTEXT"; public static final String LONGBLOB_NAME = "LONGBLOB"; public static final String LONGTEXT_NAME = "LONGTEXT"; public static final String INTERVAL_YEAR_NAME = "INTERVAL YEAR"; public static final String INTERVAL_MONTH_NAME = "INTERVAL MONTH"; public static final String INTERVAL_YEAR_MONTH_NAME = "INTERVAL YEAR TO MONTH"; public static final String INTERVAL_DAY_NAME = "INTERVAL DAY"; public static final String INTERVAL_HOUR_NAME = "INTERVAL HOUR"; public static final String INTERVAL_MINUTE_NAME = "INTERVAL MINUTE"; public static final String INTERVAL_SECOND_NAME = "INTERVAL SECOND"; public static final String INTERVAL_DAY_HOUR_NAME = "INTERVAL DAY TO HOUR"; public static final String INTERVAL_DAY_MINUTE_NAME = "INTERVAL DAY TO MINUTE"; public static final String INTERVAL_DAY_SECOND_NAME = "INTERVAL DAY TO SECOND"; public static final String INTERVAL_HOUR_MINUTE_NAME = "INTERVAL HOUR TO MINUTE"; public static final String INTERVAL_HOUR_SECOND_NAME = "INTERVAL HOUR TO SECOND"; public static final String INTERVAL_MINUTE_SECOND_NAME = "INTERVAL MINUTE TO SECOND"; // Following use of "XML" is per SQL/XML (2003) spec, // section "10.2 Type name determination". public static final String XML_NAME = "XML"; // ARRAY and STRUCT are JDBC 2.0 data types that are not // supported by Derby. public static final String ARRAY_NAME = "ARRAY"; public static final String STRUCT_NAME = "STRUCT"; // DATALINK is a JDBC 3.0 data type. Not supported by Derby. public static final String DATALINK_NAME = "DATALINK"; // ROWID and SQLXML are new types in JDBC 4.0. Not supported // by Derby. public static final String ROWID_NAME = "ROWID"; public static final String SQLXML_NAME = "SQLXML"; // MySQL compatible types. public static final String TINYINT_UNSIGNED_NAME = "TINYINT UNSIGNED"; public static final String SMALLINT_UNSIGNED_NAME = "SMALLINT UNSIGNED"; public static final String MEDIUMINT_UNSIGNED_NAME = "MEDIUMINT UNSIGNED"; public static final String INTEGER_UNSIGNED_NAME = "INTEGER UNSIGNED"; public static final String INT_UNSIGNED_NAME = "INT UNSIGNED"; public static final String LONGINT_UNSIGNED_NAME = "BIGINT UNSIGNED"; public static final String FLOAT_UNSIGNED_NAME = "FLOAT UNSIGNED"; public static final String REAL_UNSIGNED_NAME = "REAL UNSIGNED"; public static final String DOUBLE_UNSIGNED_NAME = "DOUBLE UNSIGNED"; public static final String NUMERIC_UNSIGNED_NAME = "NUMERIC UNSIGNED"; public static final String DECIMAL_UNSIGNED_NAME = "DECIMAL UNSIGNED"; public static final String DATETIME_NAME = "DATETIME"; public static final String YEAR_NAME = "YEAR"; /** * The following constants define the type precedence hierarchy. */ public static final int USER_PRECEDENCE = 1000; public static final int XML_PRECEDENCE = 180; public static final int BLOB_PRECEDENCE = 170; public static final int LONGVARBIT_PRECEDENCE = 160; public static final int VARBIT_PRECEDENCE = 150; public static final int BIT_PRECEDENCE = 140; public static final int BOOLEAN_PRECEDENCE = 130; public static final int INTERVAL_PRECEDENCE = 125; public static final int TIME_PRECEDENCE = 120; public static final int TIMESTAMP_PRECEDENCE = 110; public static final int DATE_PRECEDENCE = 100; public static final int DOUBLE_PRECEDENCE = 90; public static final int REAL_PRECEDENCE = 80; public static final int DECIMAL_PRECEDENCE = 70; public static final int NUMERIC_PRECEDENCE = 69; public static final int LONGINT_PRECEDENCE = 60; public static final int INT_PRECEDENCE = 50; public static final int SMALLINT_PRECEDENCE = 40; public static final int TINYINT_PRECEDENCE = 30; public static final int REF_PRECEDENCE = 25; public static final int CLOB_PRECEDENCE = 14; public static final int LONGVARCHAR_PRECEDENCE = 12; public static final int VARCHAR_PRECEDENCE = 10; public static final int CHAR_PRECEDENCE = 0; // This makes it easier to keep the modularity somewhat similar but // without all the extra instances. public static class FormatIds { public static final int BIT_TYPE_ID = 0; public static final int BOOLEAN_TYPE_ID = 1; public static final int CHAR_TYPE_ID = 2; public static final int DATE_TYPE_ID = 3; public static final int DECIMAL_TYPE_ID = 4; public static final int NUMERIC_TYPE_ID = 5; public static final int DOUBLE_TYPE_ID = 6; public static final int INT_TYPE_ID = 7; public static final int LONGINT_TYPE_ID = 8; public static final int LONGVARBIT_TYPE_ID = 9; public static final int LONGVARCHAR_TYPE_ID = 10; public static final int REAL_TYPE_ID = 11; public static final int REF_TYPE_ID = 12; public static final int SMALLINT_TYPE_ID = 13; public static final int TIME_TYPE_ID = 14; public static final int TIMESTAMP_TYPE_ID = 15; public static final int TINYINT_TYPE_ID = 16; public static final int USERDEFINED_TYPE_ID = 17; public static final int VARBIT_TYPE_ID = 18; public static final int BLOB_TYPE_ID = 19; public static final int VARCHAR_TYPE_ID = 20; public static final int CLOB_TYPE_ID = 21; public static final int XML_TYPE_ID = 22; public static final int ROW_MULTISET_TYPE_ID_IMPL = 23; public static final int INTERVAL_YEAR_MONTH_ID = 24; public static final int INTERVAL_DAY_SECOND_ID = 25; public static final int MEDIUMINT_ID = 26; } public static final TypeId BOOLEAN_ID = new TypeId(FormatIds.BOOLEAN_TYPE_ID); public static final TypeId SMALLINT_ID = new TypeId(FormatIds.SMALLINT_TYPE_ID); public static final TypeId MEDIUMINT_ID = new TypeId(FormatIds.MEDIUMINT_ID); public static final TypeId INTEGER_ID = new TypeId(FormatIds.INT_TYPE_ID); public static final TypeId CHAR_ID = new TypeId(FormatIds.CHAR_TYPE_ID); public static final TypeId TINYINT_ID = new TypeId(FormatIds.TINYINT_TYPE_ID); public static final TypeId BIGINT_ID = new TypeId(FormatIds.LONGINT_TYPE_ID); public static final TypeId REAL_ID = new TypeId(FormatIds.REAL_TYPE_ID); public static final TypeId DOUBLE_ID = new TypeId(FormatIds.DOUBLE_TYPE_ID); public static final TypeId DECIMAL_ID = new TypeId(FormatIds.DECIMAL_TYPE_ID); public static final TypeId NUMERIC_ID = new TypeId(FormatIds.NUMERIC_TYPE_ID); public static final TypeId VARCHAR_ID = new TypeId(FormatIds.VARCHAR_TYPE_ID); public static final TypeId DATE_ID = new TypeId(FormatIds.DATE_TYPE_ID); public static final TypeId TIME_ID = new TypeId(FormatIds.TIME_TYPE_ID); public static final TypeId TIMESTAMP_ID = new TypeId(FormatIds.TIMESTAMP_TYPE_ID); public static final TypeId BIT_ID = new TypeId(FormatIds.BIT_TYPE_ID); public static final TypeId VARBIT_ID = new TypeId(FormatIds.VARBIT_TYPE_ID); public static final TypeId REF_ID = new TypeId(FormatIds.REF_TYPE_ID); public static final TypeId LONGVARCHAR_ID = new TypeId(FormatIds.LONGVARCHAR_TYPE_ID); public static final TypeId LONGVARBIT_ID = new TypeId(FormatIds.LONGVARBIT_TYPE_ID); public static final TypeId BLOB_ID = new TypeId(FormatIds.BLOB_TYPE_ID); public static final TypeId CLOB_ID = new TypeId(FormatIds.CLOB_TYPE_ID); public static final TypeId XML_ID = new TypeId(FormatIds.XML_TYPE_ID); public static final TypeId INTERVAL_YEAR_ID = new TypeId(FormatIds.INTERVAL_YEAR_MONTH_ID, INTERVAL_YEAR_NAME); public static final TypeId INTERVAL_MONTH_ID = new TypeId(FormatIds.INTERVAL_YEAR_MONTH_ID, INTERVAL_MONTH_NAME); public static final TypeId INTERVAL_YEAR_MONTH_ID = new TypeId(FormatIds.INTERVAL_YEAR_MONTH_ID, INTERVAL_YEAR_MONTH_NAME); public static final TypeId INTERVAL_DAY_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_DAY_NAME); public static final TypeId INTERVAL_HOUR_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_HOUR_NAME); public static final TypeId INTERVAL_MINUTE_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_MINUTE_NAME); public static final TypeId INTERVAL_SECOND_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_SECOND_NAME); public static final TypeId INTERVAL_DAY_HOUR_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_DAY_HOUR_NAME); public static final TypeId INTERVAL_DAY_MINUTE_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_DAY_MINUTE_NAME); public static final TypeId INTERVAL_DAY_SECOND_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_DAY_SECOND_NAME); public static final TypeId INTERVAL_HOUR_MINUTE_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_HOUR_MINUTE_NAME); public static final TypeId INTERVAL_HOUR_SECOND_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_HOUR_SECOND_NAME); public static final TypeId INTERVAL_MINUTE_SECOND_ID = new TypeId(FormatIds.INTERVAL_DAY_SECOND_ID, INTERVAL_MINUTE_SECOND_NAME); public static final TypeId SMALLINT_UNSIGNED_ID = new TypeId(FormatIds.SMALLINT_TYPE_ID, true); public static final TypeId MEDIUMINT_UNSIGNED_ID = new TypeId(FormatIds.MEDIUMINT_ID, true); public static final TypeId INTEGER_UNSIGNED_ID = new TypeId(FormatIds.INT_TYPE_ID, true); public static final TypeId TINYINT_UNSIGNED_ID = new TypeId(FormatIds.TINYINT_TYPE_ID, true); public static final TypeId BIGINT_UNSIGNED_ID = new TypeId(FormatIds.LONGINT_TYPE_ID, true); public static final TypeId REAL_UNSIGNED_ID = new TypeId(FormatIds.REAL_TYPE_ID, true); public static final TypeId DOUBLE_UNSIGNED_ID = new TypeId(FormatIds.DOUBLE_TYPE_ID, true); public static final TypeId DECIMAL_UNSIGNED_ID = new TypeId(FormatIds.DECIMAL_TYPE_ID, true); public static final TypeId NUMERIC_UNSIGNED_ID = new TypeId(FormatIds.NUMERIC_TYPE_ID, true); public static final TypeId DATETIME_ID = new TypeId(FormatIds.TIMESTAMP_TYPE_ID, DATETIME_NAME); public static final TypeId YEAR_ID = new TypeId(FormatIds.SMALLINT_TYPE_ID, YEAR_NAME); public static final TypeId TEXT_ID = new TypeId(FormatIds.CLOB_TYPE_ID, TEXT_NAME); public static final TypeId TINYBLOB_ID = new TypeId(FormatIds.BLOB_TYPE_ID, TINYBLOB_NAME); public static final TypeId TINYTEXT_ID = new TypeId(FormatIds.CLOB_TYPE_ID, TINYTEXT_NAME); public static final TypeId MEDIUMBLOB_ID = new TypeId(FormatIds.BLOB_TYPE_ID, MEDIUMBLOB_NAME); public static final TypeId MEDIUMTEXT_ID = new TypeId(FormatIds.CLOB_TYPE_ID, MEDIUMTEXT_NAME); public static final TypeId LONGBLOB_ID = new TypeId(FormatIds.BLOB_TYPE_ID, LONGBLOB_NAME); public static final TypeId LONGTEXT_ID = new TypeId(FormatIds.CLOB_TYPE_ID, LONGTEXT_NAME); private static final TypeId[] ALL_BUILTIN_TYPE_IDS = { BOOLEAN_ID, SMALLINT_ID, MEDIUMINT_ID, INTEGER_ID, CHAR_ID, TINYINT_ID, BIGINT_ID, REAL_ID, DOUBLE_ID, DECIMAL_ID, NUMERIC_ID, VARCHAR_ID, DATE_ID, TIME_ID, TIMESTAMP_ID, BIT_ID, VARBIT_ID, REF_ID, LONGVARCHAR_ID, LONGVARBIT_ID, BLOB_ID, CLOB_ID, XML_ID, INTERVAL_YEAR_ID, INTERVAL_MONTH_ID, INTERVAL_YEAR_MONTH_ID, INTERVAL_DAY_ID, INTERVAL_HOUR_ID, INTERVAL_MINUTE_ID, INTERVAL_SECOND_ID, INTERVAL_DAY_HOUR_ID, INTERVAL_DAY_MINUTE_ID, INTERVAL_DAY_SECOND_ID, INTERVAL_HOUR_MINUTE_ID, INTERVAL_HOUR_SECOND_ID, INTERVAL_MINUTE_SECOND_ID, SMALLINT_UNSIGNED_ID, INTEGER_UNSIGNED_ID, TINYINT_UNSIGNED_ID, BIGINT_UNSIGNED_ID, REAL_UNSIGNED_ID, DOUBLE_UNSIGNED_ID, DECIMAL_UNSIGNED_ID, NUMERIC_UNSIGNED_ID, DATETIME_ID, YEAR_ID, TEXT_ID, TINYBLOB_ID, TINYTEXT_ID, MEDIUMBLOB_ID, MEDIUMTEXT_ID, LONGBLOB_ID, LONGTEXT_ID, }; /* ** Static methods to obtain TypeIds */ /** * Return all of the builtin type ids. */ public static TypeId[] getAllBuiltinTypeIds() { int count = ALL_BUILTIN_TYPE_IDS.length; TypeId[] retval = new TypeId[count]; for (int i = 0; i < count; i++) { retval[i] = ALL_BUILTIN_TYPE_IDS[i]; } return retval; } /** * Get a TypeId of the given JDBC type. This factory method is * intended to be used for built-in types. For user-defined types, * we will need a factory method that takes a Java type name. * * @param JDBCTypeId The JDBC Id of the type, as listed in * java.sql.Types * * @return The appropriate TypeId, or null if there is no such * TypeId. */ public static TypeId getBuiltInTypeId(int JDBCTypeId) { switch (JDBCTypeId) { case Types.TINYINT: return TINYINT_ID; case Types.SMALLINT: return SMALLINT_ID; case Types.INTEGER: return INTEGER_ID; case Types.BIGINT: return BIGINT_ID; case Types.FLOAT: case Types.REAL: return REAL_ID; case Types.DOUBLE: return DOUBLE_ID; case Types.DECIMAL: return DECIMAL_ID; case Types.NUMERIC: return NUMERIC_ID; case Types.CHAR: return CHAR_ID; case Types.VARCHAR: return VARCHAR_ID; case Types.DATE: return DATE_ID; case Types.TIME: return TIME_ID; case Types.TIMESTAMP: return TIMESTAMP_ID; case Types.BIT: case Types.BOOLEAN: return BOOLEAN_ID; case Types.BINARY: return BIT_ID; case Types.VARBINARY: return VARBIT_ID; case Types.LONGVARBINARY: return LONGVARBIT_ID; case Types.LONGVARCHAR: return LONGVARCHAR_ID; case Types.BLOB: return BLOB_ID; case Types.CLOB: return CLOB_ID; case Types.SQLXML: // 2009 return XML_ID; default: return null; } } public static TypeId getUserDefinedTypeId(String className, boolean delimitedIdentifier) throws StandardException { return new TypeId(className, delimitedIdentifier); } /** * This factory method is used for ANSI UDTs. If the className argument is null, * then this TypeId will have to be bound. * * @param schemaName Schema that the type definition lives in. * @param unqualifiedName The second part of the ANSI dot-separated name for the type. * @param className The Java class which is bound to the schema-qualified name by the CREATE TYPE statement. * * @return A bound type TypeId describing this ANSI UDT. */ public static TypeId getUserDefinedTypeId(String schemaName, String unqualifiedName, String className) throws StandardException { return new TypeId(schemaName, unqualifiedName, className); } /** Return true if this is this type id describes an ANSI UDT */ public boolean isAnsiUDT() { return (schemaName != null); } /** * Get a TypeId for the class that corresponds to the given Java type * name. * * @param javaTypeName The name of the Java type * * @return A TypeId for the SQL type that corresponds to the Java type, * null if there is no corresponding type. */ public static TypeId getSQLTypeForJavaType(String javaTypeName) throws StandardException { if (javaTypeName.equals("java.lang.Boolean") || javaTypeName.equals("boolean")) { return BOOLEAN_ID; } else if (javaTypeName.equals("byte[]")) { return VARBIT_ID; } else if (javaTypeName.equals("java.lang.String")) { return VARCHAR_ID; } else if (javaTypeName.equals("java.lang.Integer") || javaTypeName.equals("int")) { return INTEGER_ID; } else if (javaTypeName.equals("byte")) { return TINYINT_ID; } else if (javaTypeName.equals("short")) { return SMALLINT_ID; } else if (javaTypeName.equals("java.lang.Long") || javaTypeName.equals("long")) { return BIGINT_ID; } else if (javaTypeName.equals("java.lang.Float") || javaTypeName.equals("float")) { return REAL_ID; } else if (javaTypeName.equals("java.lang.Double") || javaTypeName.equals("double")) { return DOUBLE_ID; } else if (javaTypeName.equals("java.math.BigDecimal")) { return DECIMAL_ID; } else if (javaTypeName.equals("java.sql.Date")) { return DATE_ID; } else if (javaTypeName.equals("java.sql.Time")) { return TIME_ID; } else if (javaTypeName.equals("java.sql.Timestamp")) { return TIMESTAMP_ID; } else if (javaTypeName.equals("java.sql.Blob")) { return BLOB_ID; } else if (javaTypeName.equals("java.sql.Clob")) { return CLOB_ID; } else if (javaTypeName.equals("com.akiban.sql.types.XML")) { return XML_ID; } else { /* ** If it's a Java primitive type, return null to indicate that ** there is no corresponding SQL type (all the Java primitive ** types that have corresponding SQL types are handled above). ** ** There is only one primitive type not mentioned above, char. */ if (javaTypeName.equals("char")) { return null; } /* ** It's a non-primitive type (a class) that does not correspond ** to a SQL built-in type, so treat it as a user-defined type. */ return TypeId.getUserDefinedTypeId(javaTypeName, false); } } /** * Given a SQL type name return the corresponding TypeId. * @param SQLTypeName Name of SQL type * @return TypeId or null if there is no corresponding SQL type. */ public static TypeId getBuiltInTypeId(String SQLTypeName) { if (SQLTypeName.equals(BOOLEAN_NAME)) { return BOOLEAN_ID; } if (SQLTypeName.equals(CHAR_NAME)) { return CHAR_ID; } if (SQLTypeName.equals(DATE_NAME)) { return DATE_ID; } if (SQLTypeName.equals(DOUBLE_NAME)) { return DOUBLE_ID; } if (SQLTypeName.equals(FLOAT_NAME)) { return REAL_ID; } if (SQLTypeName.equals(MEDIUMINT_NAME)) return MEDIUMINT_ID; if (SQLTypeName.equals(INTEGER_NAME) || SQLTypeName.equals(INT_NAME)) { return INTEGER_ID; } if (SQLTypeName.equals(LONGINT_NAME)) { return BIGINT_ID; } if (SQLTypeName.equals(REAL_NAME)) { return REAL_ID; } if (SQLTypeName.equals(SMALLINT_NAME)) { return SMALLINT_ID; } if (SQLTypeName.equals(TIME_NAME)) { return TIME_ID; } if (SQLTypeName.equals(TIMESTAMP_NAME)) { return TIMESTAMP_ID; } if (SQLTypeName.equals(VARCHAR_NAME)) { return VARCHAR_ID; } if (SQLTypeName.equals(BIT_NAME)) { return BIT_ID; } if (SQLTypeName.equals(VARBIT_NAME)) { return VARBIT_ID; } if (SQLTypeName.equals(TINYINT_NAME)) { return TINYINT_ID; } if (SQLTypeName.equals(DECIMAL_NAME)) { return DECIMAL_ID; } if (SQLTypeName.equals(NUMERIC_NAME)) { return NUMERIC_ID; } if (SQLTypeName.equals(LONGVARCHAR_NAME)) { return LONGVARCHAR_ID; } if (SQLTypeName.equals(LONGVARBIT_NAME)) { return LONGVARBIT_ID; } if (SQLTypeName.equals(BLOB_NAME)) { return BLOB_ID; } if (SQLTypeName.equals(CLOB_NAME)) { return CLOB_ID; } if (SQLTypeName.equals(TEXT_NAME)) { return TEXT_ID; } if (SQLTypeName.equals(TINYBLOB_NAME)) { return TINYBLOB_ID; } if (SQLTypeName.equals(TINYTEXT_NAME)) { return TINYTEXT_ID; } if (SQLTypeName.equals(MEDIUMBLOB_NAME)) { return MEDIUMBLOB_ID; } if (SQLTypeName.equals(MEDIUMTEXT_NAME)) { return MEDIUMTEXT_ID; } if (SQLTypeName.equals(LONGBLOB_NAME)) { return LONGBLOB_ID; } if (SQLTypeName.equals(LONGTEXT_NAME)) { return LONGTEXT_ID; } if (SQLTypeName.equals(XML_NAME)) { return XML_ID; } if (SQLTypeName.equals(INTERVAL_YEAR_NAME)) { return INTERVAL_YEAR_ID; } if (SQLTypeName.equals(INTERVAL_MONTH_NAME)) { return INTERVAL_MONTH_ID; } if (SQLTypeName.equals(INTERVAL_YEAR_MONTH_NAME)) { return INTERVAL_YEAR_MONTH_ID; } if (SQLTypeName.equals(INTERVAL_DAY_NAME)) { return INTERVAL_DAY_ID; } if (SQLTypeName.equals(INTERVAL_HOUR_NAME)) { return INTERVAL_HOUR_ID; } if (SQLTypeName.equals(INTERVAL_MINUTE_NAME)) { return INTERVAL_MINUTE_ID; } if (SQLTypeName.equals(INTERVAL_SECOND_NAME)) { return INTERVAL_SECOND_ID; } if (SQLTypeName.equals(INTERVAL_DAY_HOUR_NAME)) { return INTERVAL_DAY_HOUR_ID; } if (SQLTypeName.equals(INTERVAL_DAY_MINUTE_NAME)) { return INTERVAL_DAY_MINUTE_ID; } if (SQLTypeName.equals(INTERVAL_DAY_SECOND_NAME)) { return INTERVAL_DAY_SECOND_ID; } if (SQLTypeName.equals(INTERVAL_HOUR_MINUTE_NAME)) { return INTERVAL_HOUR_MINUTE_ID; } if (SQLTypeName.equals(INTERVAL_HOUR_SECOND_NAME)) { return INTERVAL_HOUR_SECOND_ID; } if (SQLTypeName.equals(INTERVAL_MINUTE_SECOND_NAME)) { return INTERVAL_MINUTE_SECOND_ID; } if (SQLTypeName.equals(TINYINT_UNSIGNED_NAME)) { return TINYINT_UNSIGNED_ID; } if (SQLTypeName.equals(SMALLINT_UNSIGNED_NAME)) { return SMALLINT_UNSIGNED_ID; } if (SQLTypeName.equals(INTEGER_UNSIGNED_NAME) || SQLTypeName.equals(INT_UNSIGNED_NAME)) { return INTEGER_UNSIGNED_ID; } if (SQLTypeName.equals(LONGINT_UNSIGNED_NAME)) { return BIGINT_UNSIGNED_ID; } if (SQLTypeName.equals(FLOAT_UNSIGNED_NAME)) { return REAL_UNSIGNED_ID; } if (SQLTypeName.equals(REAL_UNSIGNED_NAME)) { return REAL_UNSIGNED_ID; } if (SQLTypeName.equals(DOUBLE_UNSIGNED_NAME)) { return DOUBLE_UNSIGNED_ID; } if (SQLTypeName.equals(NUMERIC_UNSIGNED_NAME)) { return NUMERIC_UNSIGNED_ID; } if (SQLTypeName.equals(DECIMAL_UNSIGNED_NAME)) { return DECIMAL_UNSIGNED_ID; } if (SQLTypeName.equals(DATETIME_NAME)) { return DATETIME_ID; } if (SQLTypeName.equals(YEAR_NAME)) { return YEAR_ID; } // Types defined below here are SQL types and non-JDBC types that are // supported by Derby if (SQLTypeName.equals(REF_NAME)) { return REF_ID; } return null; } /* * * Instance fields and methods */ /* Set in setTypeIdSpecificInstanceVariables() as needed */ private int formatId; private String schemaName; private String unqualifiedName; private int JDBCTypeId; private String javaTypeName; private boolean classNameWasDelimitedIdentifier; private boolean isBitTypeId; private boolean isLOBTypeId; private boolean isBooleanTypeId; private boolean isConcatableTypeId; private boolean isDecimalTypeId; private boolean isLongConcatableTypeId; private boolean isNumericTypeId; private boolean isRefTypeId; private boolean isStringTypeId; private boolean isFloatingPointTypeId; private boolean isRealTypeId; private boolean isDateTimeTimeStampTypeId; private boolean isIntervalTypeId; private boolean isUserDefinedTypeId; private boolean isComparable; private int maxPrecision; private int maxScale; private int maxMaxWidth; private int typePrecedence; /** * Constructor for a TypeId * * @param formatId Internal format id */ private TypeId(int formatId) { this.formatId = formatId; // most types are comparable to themselves (with a few exceptions) isComparable = true; switch (formatId) { case FormatIds.BIT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.BIT_NAME; JDBCTypeId = Types.BINARY; typePrecedence = BIT_PRECEDENCE; javaTypeName = "byte[]"; maxMaxWidth = TypeId.BIT_MAXWIDTH; isBitTypeId = true; isConcatableTypeId = true; break; case FormatIds.BOOLEAN_TYPE_ID: schemaName = null; unqualifiedName = TypeId.BOOLEAN_NAME; JDBCTypeId = Types.BOOLEAN; maxPrecision = TypeId.BOOLEAN_MAXWIDTH; typePrecedence = BOOLEAN_PRECEDENCE; javaTypeName = "java.lang.Boolean"; maxMaxWidth = TypeId.BOOLEAN_MAXWIDTH; isBooleanTypeId = true; break; case FormatIds.CHAR_TYPE_ID: schemaName = null; unqualifiedName = TypeId.CHAR_NAME; JDBCTypeId = Types.CHAR; typePrecedence = CHAR_PRECEDENCE; javaTypeName = "java.lang.String"; maxMaxWidth = TypeId.CHAR_MAXWIDTH; isStringTypeId = true; isConcatableTypeId = true; break; case FormatIds.DATE_TYPE_ID: schemaName = null; unqualifiedName = TypeId.DATE_NAME; JDBCTypeId = Types.DATE; typePrecedence = DATE_PRECEDENCE; javaTypeName = "java.sql.Date"; maxMaxWidth = TypeId.DATE_MAXWIDTH; maxPrecision = TypeId.DATE_MAXWIDTH; isDateTimeTimeStampTypeId = true; break; case FormatIds.DECIMAL_TYPE_ID: schemaName = null; unqualifiedName = TypeId.DECIMAL_NAME; JDBCTypeId = Types.DECIMAL; maxPrecision = TypeId.DECIMAL_PRECISION; maxScale = TypeId.DECIMAL_SCALE; typePrecedence = DECIMAL_PRECEDENCE; javaTypeName = "java.math.BigDecimal"; maxMaxWidth = TypeId.DECIMAL_MAXWIDTH; isDecimalTypeId = true; isNumericTypeId = true; break; case FormatIds.NUMERIC_TYPE_ID: schemaName = null; unqualifiedName = TypeId.NUMERIC_NAME; JDBCTypeId = Types.NUMERIC; maxPrecision = TypeId.DECIMAL_PRECISION; maxScale = TypeId.DECIMAL_SCALE; typePrecedence = DECIMAL_PRECEDENCE; javaTypeName = "java.math.BigDecimal"; maxMaxWidth = TypeId.DECIMAL_MAXWIDTH; isDecimalTypeId = true; isNumericTypeId = true; break; case FormatIds.DOUBLE_TYPE_ID: schemaName = null; unqualifiedName = TypeId.DOUBLE_NAME; JDBCTypeId = Types.DOUBLE; maxPrecision = TypeId.DOUBLE_PRECISION; maxScale = TypeId.DOUBLE_SCALE; typePrecedence = DOUBLE_PRECEDENCE; javaTypeName = "java.lang.Double"; maxMaxWidth = TypeId.DOUBLE_MAXWIDTH; isNumericTypeId = true; isFloatingPointTypeId = true; break; case FormatIds.MEDIUMINT_ID: schemaName = null; unqualifiedName = TypeId.MEDIUMINT_NAME; JDBCTypeId = Types.OTHER; maxPrecision = TypeId.INT_PRECISION; maxScale = TypeId.INT_SCALE; typePrecedence = INT_PRECEDENCE; javaTypeName = "java.lang.Integer"; maxMaxWidth = TypeId.INT_MAXWIDTH; isNumericTypeId = true; break; case FormatIds.INT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.INTEGER_NAME; JDBCTypeId = Types.INTEGER; maxPrecision = TypeId.INT_PRECISION; maxScale = TypeId.INT_SCALE; typePrecedence = INT_PRECEDENCE; javaTypeName = "java.lang.Integer"; maxMaxWidth = TypeId.INT_MAXWIDTH; isNumericTypeId = true; break; case FormatIds.LONGINT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.LONGINT_NAME; JDBCTypeId = Types.BIGINT; maxPrecision = TypeId.LONGINT_PRECISION; maxScale = TypeId.LONGINT_SCALE; typePrecedence = LONGINT_PRECEDENCE; javaTypeName = "java.lang.Long"; maxMaxWidth = TypeId.LONGINT_MAXWIDTH; isNumericTypeId = true; break; case FormatIds.LONGVARBIT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.LONGVARBIT_NAME; JDBCTypeId = Types.LONGVARBINARY; typePrecedence = LONGVARBIT_PRECEDENCE; javaTypeName = "byte[]"; maxMaxWidth = TypeId.LONGVARBIT_MAXWIDTH; isBitTypeId = true; isConcatableTypeId = true; isLongConcatableTypeId = true; break; case FormatIds.LONGVARCHAR_TYPE_ID: schemaName = null; unqualifiedName = TypeId.LONGVARCHAR_NAME; JDBCTypeId = Types.LONGVARCHAR; typePrecedence = LONGVARCHAR_PRECEDENCE; javaTypeName = "java.lang.String"; maxMaxWidth = TypeId.LONGVARCHAR_MAXWIDTH; isStringTypeId = true; isConcatableTypeId = true; isLongConcatableTypeId = true; isComparable = false; break; case FormatIds.REAL_TYPE_ID: schemaName = null; unqualifiedName = TypeId.REAL_NAME; JDBCTypeId = Types.REAL; maxPrecision = TypeId.REAL_PRECISION; maxScale = TypeId.REAL_SCALE; typePrecedence = REAL_PRECEDENCE; javaTypeName = "java.lang.Float"; maxMaxWidth = TypeId.REAL_MAXWIDTH; isNumericTypeId = true; isRealTypeId = true; isFloatingPointTypeId = true; break; case FormatIds.REF_TYPE_ID: schemaName = null; unqualifiedName = TypeId.REF_NAME; JDBCTypeId = Types.OTHER; typePrecedence = REF_PRECEDENCE; javaTypeName = "java.sql.Ref"; isRefTypeId = true; isComparable = false; break; case FormatIds.SMALLINT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.SMALLINT_NAME; JDBCTypeId = Types.SMALLINT; maxPrecision = TypeId.SMALLINT_PRECISION; maxScale = TypeId.SMALLINT_SCALE; typePrecedence = SMALLINT_PRECEDENCE; javaTypeName = "java.lang.Integer"; maxMaxWidth = TypeId.SMALLINT_MAXWIDTH; isNumericTypeId = true; break; case FormatIds.TIME_TYPE_ID: schemaName = null; unqualifiedName = TypeId.TIME_NAME; JDBCTypeId = Types.TIME; typePrecedence = TIME_PRECEDENCE; javaTypeName = "java.sql.Time"; maxScale = TypeId.TIME_SCALE; maxMaxWidth = TypeId.TIME_MAXWIDTH; maxPrecision = TypeId.TIME_MAXWIDTH; isDateTimeTimeStampTypeId = true; break; case FormatIds.TIMESTAMP_TYPE_ID: schemaName = null; unqualifiedName = TypeId.TIMESTAMP_NAME; JDBCTypeId = Types.TIMESTAMP; typePrecedence = TIMESTAMP_PRECEDENCE; javaTypeName = "java.sql.Timestamp"; maxScale = TypeId.TIMESTAMP_SCALE; maxMaxWidth = TypeId.TIMESTAMP_MAXWIDTH; maxPrecision = TypeId.TIMESTAMP_MAXWIDTH; isDateTimeTimeStampTypeId = true; break; case FormatIds.TINYINT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.TINYINT_NAME; JDBCTypeId = Types.TINYINT; maxPrecision = TypeId.TINYINT_PRECISION; maxScale = TypeId.TINYINT_SCALE; typePrecedence = TINYINT_PRECEDENCE; javaTypeName = "java.lang.Integer"; maxMaxWidth = TypeId.TINYINT_MAXWIDTH; isNumericTypeId = true; break; case FormatIds.VARBIT_TYPE_ID: schemaName = null; unqualifiedName = TypeId.VARBIT_NAME; JDBCTypeId = Types.VARBINARY; typePrecedence = VARBIT_PRECEDENCE; javaTypeName = "byte[]"; maxMaxWidth = TypeId.VARBIT_MAXWIDTH; isBitTypeId = true; isConcatableTypeId = true; break; case FormatIds.BLOB_TYPE_ID: schemaName = null; unqualifiedName = TypeId.BLOB_NAME; JDBCTypeId = Types.BLOB; typePrecedence = BLOB_PRECEDENCE; javaTypeName = "java.sql.Blob"; maxMaxWidth = TypeId.BLOB_MAXWIDTH; isBitTypeId = true; isConcatableTypeId = true; isComparable = false; isLOBTypeId = true; break; case FormatIds.VARCHAR_TYPE_ID: schemaName = null; unqualifiedName = TypeId.VARCHAR_NAME; JDBCTypeId = Types.VARCHAR; typePrecedence = VARCHAR_PRECEDENCE; javaTypeName = "java.lang.String"; maxMaxWidth = TypeId.VARCHAR_MAXWIDTH; isStringTypeId = true; isConcatableTypeId = true; break; case FormatIds.CLOB_TYPE_ID: schemaName = null; unqualifiedName = TypeId.CLOB_NAME; JDBCTypeId = Types.CLOB; typePrecedence = CLOB_PRECEDENCE; javaTypeName = "java.sql.Clob"; maxMaxWidth = TypeId.CLOB_MAXWIDTH; isStringTypeId = true; isConcatableTypeId = true; isComparable = false; isLOBTypeId = true; break; case FormatIds.XML_TYPE_ID: schemaName = null; unqualifiedName = TypeId.XML_NAME; JDBCTypeId = Types.SQLXML; typePrecedence = XML_PRECEDENCE; javaTypeName = "com.akiban.sql.types.XML"; maxMaxWidth = TypeId.XML_MAXWIDTH; isComparable = false; break; case FormatIds.INTERVAL_YEAR_MONTH_ID: schemaName = null; typePrecedence = INTERVAL_PRECEDENCE; JDBCTypeId = Types.OTHER; maxPrecision = TypeId.INTERVAL_YEAR_MONTH_PRECISION; maxScale = TypeId.INTERVAL_YEAR_MONTH_SCALE; maxMaxWidth = TypeId.INTERVAL_YEAR_MONTH_MAXWIDTH; isIntervalTypeId = true; break; case FormatIds.INTERVAL_DAY_SECOND_ID: schemaName = null; typePrecedence = INTERVAL_PRECEDENCE; JDBCTypeId = Types.OTHER; maxPrecision = TypeId.INTERVAL_DAY_SECOND_PRECISION; maxScale = TypeId.INTERVAL_DAY_SECOND_SCALE; maxMaxWidth = TypeId.INTERVAL_DAY_SECOND_MAXWIDTH; isIntervalTypeId = true; break; case FormatIds.USERDEFINED_TYPE_ID: JDBCTypeId = java.sql.Types.JAVA_OBJECT; maxMaxWidth = -1; isUserDefinedTypeId = true; typePrecedence = USER_PRECEDENCE; break; case FormatIds.ROW_MULTISET_TYPE_ID_IMPL: schemaName = null; JDBCTypeId = Types.OTHER; javaTypeName = "java.sql.ResultSet"; maxMaxWidth = -1; break; default: assert false; break; } } public int getTypeFormatId() { return formatId; } private boolean unsigned; private TypeId(int formatId, boolean unsigned) { this(formatId); if (unsigned) { this.unsigned = true; switch (formatId) { case FormatIds.DECIMAL_TYPE_ID: unqualifiedName = TypeId.DECIMAL_UNSIGNED_NAME; break; case FormatIds.NUMERIC_TYPE_ID: unqualifiedName = TypeId.NUMERIC_UNSIGNED_NAME; break; case FormatIds.DOUBLE_TYPE_ID: unqualifiedName = TypeId.DOUBLE_UNSIGNED_NAME; break; case FormatIds.INT_TYPE_ID: unqualifiedName = TypeId.INTEGER_UNSIGNED_NAME; break; case FormatIds.LONGINT_TYPE_ID: unqualifiedName = TypeId.LONGINT_UNSIGNED_NAME; break; case FormatIds.REAL_TYPE_ID: unqualifiedName = TypeId.REAL_UNSIGNED_NAME; break; case FormatIds.SMALLINT_TYPE_ID: unqualifiedName = TypeId.SMALLINT_UNSIGNED_NAME; break; case FormatIds.TINYINT_TYPE_ID: unqualifiedName = TypeId.TINYINT_UNSIGNED_NAME; break; case FormatIds.MEDIUMINT_ID: unqualifiedName = TypeId.MEDIUMINT_UNSIGNED_NAME; break; default: assert false : "unknown formatId: " + formatId; } } } private TypeId(int formatId, String name) { this(formatId); unqualifiedName = name; } /** * Constructor for a TypeId for user defined types * * @param className The class name / delimited identifier. * @param classNameWasDelimitedIdentifier Whether or not the class name * was a delimited identifier. */ private TypeId(String className, boolean classNameWasDelimitedIdentifier) { this(FormatIds.USERDEFINED_TYPE_ID); if (classNameWasDelimitedIdentifier) { // TODO: Need to split? } else { schemaName = null; unqualifiedName = className; } javaTypeName = className; this.classNameWasDelimitedIdentifier = classNameWasDelimitedIdentifier; } private TypeId(String schemaName, String unqualifiedName, String className) { this(FormatIds.USERDEFINED_TYPE_ID); this.schemaName = schemaName; this.unqualifiedName = unqualifiedName; this.javaTypeName = className; } /** * we want equals to say if these are the same type id or not. */ public boolean equals(Object that) { if (that instanceof TypeId) return this.getSQLTypeName().equals(((TypeId)that).getSQLTypeName()); else return false; } /* Hashcode which works with equals. */ public int hashCode() { return this.getSQLTypeName().hashCode(); } /** * JDBC has its own idea of type identifiers which is different from * the Derby internal type ids. The JDBC type ids are defined * as public final static ints in java.sql.Types. This method translates * a Derby internal TypeId to a JDBC type id. For java objects this * returns JAVA_OBJECT in Java2 and OTHER in JDK 1.1. For Boolean datatypes, * this returns Type.BOOLEAN in JDK1.4 and Type.BIT for jdks prior to 1.4 * * @return The JDBC type Id for this type */ public final int getJDBCTypeId() { return JDBCTypeId; } /** * Returns the SQL name of the datatype. If it is a user-defined type, * it returns the full Java path name for the datatype, meaning the * dot-separated path including the package names. * * @return A String containing the SQL name of this type. */ public String getSQLTypeName() { if (schemaName == null) { return unqualifiedName; } else { // TODO: Need some quotes? return schemaName + "." + unqualifiedName; } } /** * Tell whether this is a built-in type. * NOTE: There are 3 "classes" of types: * built-in - system provided types which are implemented internally * (int, smallint, etc.) * system built-in - system provided types, independent of implementation * (date, time, etc.) * user types - types implemented outside of the system * (java.lang.Integer, asdf.asdf.asdf, etc.) * * @return false for built-in types, true for user-defined types. */ public final boolean userType() { return isUserDefinedTypeId; } /** * Get the maximum precision of the type. For types with variable * precision, this is an arbitrary high precision. * * @return The maximum precision of the type */ public int getMaximumPrecision() { return maxPrecision; } /** * Get the maximum scale of the type. For types with variable scale, * this is an arbitrary high scale. * * @return The maximum scale of the type */ public int getMaximumScale() { return maxScale; } /** * For user types, tell whether or not the class name was a * delimited identifier. For all other types, return false. * * @return Whether or not the class name was a delimited identifier. */ public boolean getClassNameWasDelimitedIdentifier() { return classNameWasDelimitedIdentifier; } /** * Does this TypeId represent a TypeId for a StringDataType. * * @return Whether or not this TypeId represents a TypeId for a StringDataType. */ public boolean isStringTypeId() { return isStringTypeId; } /** * Is this a TypeId for DATE/TIME/TIMESTAMP * * @return true if this is a DATE/TIME/TIMESTAMP */ public boolean isDateTimeTimeStampTypeId() { return isDateTimeTimeStampTypeId; } /** * Is this a TypeId for REAL * * @return true if this is a REAL */ public boolean isRealTypeId() { return isRealTypeId; } /** * Is this a TypeId for floating point (REAL/DOUBLE) * * @return true if this is a REAL or DOUBLE */ public boolean isFloatingPointTypeId() { return isFloatingPointTypeId; } /** * Is this a TypeId for DOUBLE * * @return true if this is a DOUBLE */ public boolean isDoubleTypeId() { return isFloatingPointTypeId && (!isRealTypeId); } /** * Is this a fixed string type? * @return true if this is CHAR */ public boolean isFixedStringTypeId() { return (formatId == FormatIds.CHAR_TYPE_ID); } /** *Is this a Clob? * @return true if this is CLOB */ public boolean isClobTypeId() { return (formatId == FormatIds.CLOB_TYPE_ID); } /** *Is this a Blob? * @return true if this is BLOB */ public boolean isBlobTypeId() { return (formatId == FormatIds.BLOB_TYPE_ID); } /** *Is this a LongVarchar? * @return true if this is LongVarchar */ public boolean isLongVarcharTypeId() { return (formatId == FormatIds.LONGVARCHAR_TYPE_ID); } /** *Is this a LongVarbinary? * @return true if this is LongVarbinary */ public boolean isLongVarbinaryTypeId() { return (formatId == FormatIds.LONGVARBIT_TYPE_ID); } /** * Is this DATE/TIME or TIMESTAMP? * * @return true if this DATE/TIME or TIMESTAMP */ public boolean isDateTimeTimeStampTypeID() { return ((formatId == FormatIds.DATE_TYPE_ID) || (formatId == FormatIds.TIME_TYPE_ID) || (formatId == FormatIds.TIMESTAMP_TYPE_ID)); } /** *Is this an XML doc? * @return true if this is XML */ public boolean isXMLTypeId() { return (formatId == FormatIds.XML_TYPE_ID); } /** * @return <code>false</code> if this type is not comparable to any other types or even to itself * <code>true</code> otherwise. */ public boolean isComparable() { return isComparable; } /** * Each built-in type in JSQL has a precedence. This precedence determines * how to do type promotion when using binary operators. For example, float * has a higher precedence than int, so when adding an int to a float, the * result type is float. * * The precedence for some types is arbitrary. For example, it doesn't * matter what the precedence of the boolean type is, since it can't be * mixed with other types. But the precedence for the number types is * critical. The SQL standard requires that exact numeric types be * promoted to approximate numeric when one operator uses both. Also, * the precedence is arranged so that one will not lose precision when * promoting a type. * NOTE: char, varchar, and longvarchar must appear at the bottom of * the hierarchy, but above USER_PRECEDENCE, since we allow the implicit * conversion of those types to any other built-in system type. * * @return The precedence of this type. */ public int typePrecedence() { return typePrecedence; } /** * Get the name of the corresponding Java type. * * Each SQL type has a corresponding Java type. When a SQL value is * passed to a Java method, it is translated to its corresponding Java * type. For example, when a SQL date column is passed to a method, * it is translated to a java.sql.Date. * * @return The name of the corresponding Java type. */ public String getCorrespondingJavaTypeName() { return javaTypeName; } /** * Get the name of the corresponding Java type. * * This method is used directly from EmbedResultSetMetaData (jdbc) * to return the corresponding type (as choosen by getObject). * It solves a specific problem for BLOB types where the * getCorrespondingJavaTypeName() is used internally for casting * which doesn't work if changed from byte[] to java.sql.Blob. * So we do it here instead, to avoid unexpected side effects. * * @return The name of the corresponding Java type. */ public String getResultSetMetaDataTypeName() { if (BLOB_ID.equals(this)) return "java.sql.Blob"; if (CLOB_ID.equals(this)) return "java.sql.Clob"; return getCorrespondingJavaTypeName(); } /** * Get the maximum maximum width of the type (that's not a typo). For * types with variable length, this is the absolute maximum for the type. * * @return The maximum maximum width of the type */ public int getMaximumMaximumWidth() { return maxMaxWidth; } /** * Converts this TypeId, given a data type descriptor (including length/precision), * to a string. E.g. * * VARCHAR(30) * * * For most data types, we just return the SQL type name. * * @param dts Data type descriptor that holds the length/precision etc. as necessary * * @return String version of datatype, suitable for running through * the Parser. */ // TODO: Consider consolitation with DataTypeDescriptor.getFullSQLTypeName(). public String toParsableString(DataTypeDescriptor dts) { String retval = getSQLTypeName(); switch (formatId) { case FormatIds.BIT_TYPE_ID: case FormatIds.VARBIT_TYPE_ID: int rparen = retval.indexOf(')'); String lead = retval.substring(0, rparen); retval = lead + dts.getMaximumWidth() + retval.substring(rparen); break; case FormatIds.CHAR_TYPE_ID: case FormatIds.VARCHAR_TYPE_ID: case FormatIds.BLOB_TYPE_ID: case FormatIds.CLOB_TYPE_ID: retval += "(" + dts.getMaximumWidth() + ")"; break; case FormatIds.DECIMAL_TYPE_ID: if (unsigned) { retval = retval.substring(0, retval.length() - 9) + "(" + dts.getPrecision() + "," + dts.getScale() + ")" + retval.substring(retval.length() - 9); } else retval += "(" + dts.getPrecision() + "," + dts.getScale() + ")"; break; case FormatIds.INTERVAL_YEAR_MONTH_ID: case FormatIds.INTERVAL_DAY_SECOND_ID: if (this == INTERVAL_SECOND_ID) { if (dts.getPrecision() > 0) { retval += "(" + dts.getPrecision(); if (dts.getScale() > 0) retval += ", " + dts.getScale(); retval += ")"; } } else { if (dts.getPrecision() > 0) { int idx = retval.indexOf(" ", 9); if (idx < 0) idx = retval.length(); retval = retval.substring(0, idx) + "(" + dts.getPrecision() + ")" + retval.substring(idx); } if (dts.getScale() > 0) retval += "(" + dts.getScale() +")"; } break; } return retval; } /** * Is this a type id for a numeric type? * * @return Whether or not this a type id for a numeric type. */ public boolean isNumericTypeId() { return isNumericTypeId; } /** * Is this a type id for a decimal type? * * @return Whether or not this a type id for a decimal type. */ public boolean isDecimalTypeId() { return isDecimalTypeId; } /** * Is this a type id for an integer type? * * @return Whether or not this a type id for a integer type. */ public boolean isIntegerTypeId() { return isNumericTypeId && !isDecimalTypeId && !isFloatingPointTypeId; } /** * Is this a type id for a boolean type? * * @return Whether or not this a type id for a boolean type. */ public boolean isBooleanTypeId() { return isBooleanTypeId; } /** * Is this a type id for a ref type? * * @return Whether or not this a type id for a ref type. */ public boolean isRefTypeId() { return isRefTypeId; } /** * Is this a type id for a concatable type? * * @return Whether or not this a type id for a concatable type. */ public boolean isConcatableTypeId() { return isConcatableTypeId; } /** * Is this a type id for a bit type? * * @return Whether or not this a type id for a bit type. */ public boolean isBitTypeId() { return isBitTypeId; } /** * Is this a type id for a LOB type? * * @return Whether or not this a type id for a LOB type. */ public boolean isLOBTypeId() { return isLOBTypeId; } /** * Is this a type id for a long concatable type? * * @return Whether or not this a type id for a long concatable type. */ public boolean isLongConcatableTypeId() { return isLongConcatableTypeId; } /** * Is this a type id for a user defined type? * * @return Whether or not this a type id for a user defined type. */ public boolean isUserDefinedTypeId() { return isUserDefinedTypeId; } /** * Get the precision of the merge of two Decimals * * @param leftType the left type * @param rightType the left type * * @return the resultant precision */ public int getPrecision(DataTypeDescriptor leftType, DataTypeDescriptor rightType) { long lscale = (long)leftType.getScale(); long rscale = (long)rightType.getScale(); long lprec = (long)leftType.getPrecision(); long rprec = (long)rightType.getPrecision(); long val; assert (formatId == FormatIds.DECIMAL_TYPE_ID) : formatId; /* ** Take the maximum left of decimal digits plus the scale. */ val = this.getScale(leftType, rightType) + Math.max(lprec - lscale, rprec - rscale); if (val > Integer.MAX_VALUE) { val = Integer.MAX_VALUE; } return (int)val; } /** * Get the scale of the merge of two decimals * * @param leftType the left type * @param rightType the left type * * @return the resultant precision */ public int getScale(DataTypeDescriptor leftType, DataTypeDescriptor rightType) { assert (formatId == FormatIds.DECIMAL_TYPE_ID) : formatId; /* ** Retain greatest scale */ return Math.max(leftType.getScale(), rightType.getScale()); } /** * Does type hava a declared variable length (defined by the application). * Examples are CHAR(10), CLOB(1M). * Unbounded long types, like LONG VARCHAR return false here. * @return boolean true if type is variable length false if not. */ public boolean variableLength() { switch (formatId) { case FormatIds.BIT_TYPE_ID: case FormatIds.VARBIT_TYPE_ID: case FormatIds.DECIMAL_TYPE_ID: case FormatIds.CHAR_TYPE_ID: case FormatIds.VARCHAR_TYPE_ID: case FormatIds.BLOB_TYPE_ID: case FormatIds.CLOB_TYPE_ID: return true; default: return false; } } public static class RowMultiSetTypeId extends TypeId { String[] columnNames; DataTypeDescriptor[] columnTypes; public RowMultiSetTypeId(String[] columnNames, DataTypeDescriptor[] columnTypes) { super(FormatIds.ROW_MULTISET_TYPE_ID_IMPL); this.columnNames = columnNames; this.columnTypes = columnTypes; } /** * <p> * Get the SQL name of this multi set. This is the name suitable for * replaying the DDL to create a Table Function. * </p> */ public String getSQLTypeName() { StringBuffer buffer = new StringBuffer(); int count = columnNames.length; buffer.append("TABLE ( "); for (int i = 0; i < count; i++) { if (i > 0) { buffer.append( ", " ); } buffer.append('\"'); buffer.append(columnNames[i]); buffer.append('\"'); buffer.append(' '); buffer.append(columnTypes[i].getSQLstring()); } buffer.append( " )" ); return buffer.toString(); } public boolean isRowMultiSet() { return true; } public String[] getColumnNames() { return columnNames; } public DataTypeDescriptor[] getColumnTypes() { return columnTypes; } } public static TypeId getRowMultiSet(String[] columnNames, DataTypeDescriptor[] columnTypes) { return new RowMultiSetTypeId(columnNames, columnTypes); } public boolean isRowMultiSet() { return false; } /** Is this one of the unsigned numeric types? */ public boolean isUnsigned() { return unsigned; } public static TypeId intervalTypeId(TypeId startField, TypeId endField) throws StandardException { if (startField == INTERVAL_YEAR_ID) { if (endField == INTERVAL_MONTH_ID) return INTERVAL_YEAR_MONTH_ID; } if (startField == INTERVAL_DAY_ID) { if (endField == INTERVAL_HOUR_ID) return INTERVAL_DAY_HOUR_ID; if (endField == INTERVAL_MINUTE_ID) return INTERVAL_DAY_MINUTE_ID; if (endField == INTERVAL_SECOND_ID) return INTERVAL_DAY_SECOND_ID; } if (startField == INTERVAL_HOUR_ID) { if (endField == INTERVAL_MINUTE_ID) return INTERVAL_HOUR_MINUTE_ID; if (endField == INTERVAL_SECOND_ID) return INTERVAL_HOUR_SECOND_ID; } if (startField == INTERVAL_MINUTE_ID) { if (endField == INTERVAL_SECOND_ID) return INTERVAL_MINUTE_SECOND_ID; } throw new StandardException("Illegal " + startField.unqualifiedName + " TO " + endField.unqualifiedName.substring("INTERVAL ".length())); } public boolean isIntervalTypeId() { return isIntervalTypeId; } }