0001: /*
0002:
0003: Derby - Class org.apache.derby.iapi.types.TypeId
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.iapi.types;
0023:
0024: import org.apache.derby.iapi.services.io.Formatable;
0025: import org.apache.derby.iapi.services.io.StoredFormatIds;
0026: import org.apache.derby.iapi.services.monitor.Monitor;
0027: import org.apache.derby.iapi.services.loader.ClassFactory;
0028:
0029: import org.apache.derby.iapi.error.StandardException;
0030:
0031: import org.apache.derby.catalog.types.BaseTypeIdImpl;
0032: import org.apache.derby.catalog.types.DecimalTypeIdImpl;
0033: import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;
0034:
0035: import org.apache.derby.iapi.reference.Limits;
0036:
0037: import java.io.ObjectOutput;
0038: import java.io.ObjectInput;
0039: import java.io.IOException;
0040: import org.apache.derby.iapi.services.sanity.SanityManager;
0041:
0042: import org.apache.derby.iapi.types.*;
0043: import org.apache.derby.iapi.types.*;
0044:
0045: import org.apache.derby.iapi.reference.JDBC20Translation;
0046: import org.apache.derby.iapi.reference.JDBC30Translation;
0047:
0048: import java.sql.Types;
0049:
0050: /**
0051: * The TypeId interface provides methods to get information about datatype ids.
0052:
0053: <P>
0054: * The equals(Object) method can be used to determine if two typeIds are for the same type,
0055: * which defines type id equality.
0056:
0057: *
0058: * @author Jeff Lichtman
0059: */
0060:
0061: public final class TypeId implements Formatable {
0062: /**
0063: * Various fixed numbers related to datatypes.
0064: */
0065: public static final int LONGINT_PRECISION = 19;
0066: public static final int LONGINT_SCALE = 0;
0067: public static final int LONGINT_MAXWIDTH = 8;
0068:
0069: public static final int INT_PRECISION = 10;
0070: public static final int INT_SCALE = 0;
0071: public static final int INT_MAXWIDTH = 4;
0072:
0073: public static final int SMALLINT_PRECISION = 5;
0074: public static final int SMALLINT_SCALE = 0;
0075: public static final int SMALLINT_MAXWIDTH = 2;
0076:
0077: public static final int TINYINT_PRECISION = 3;
0078: public static final int TINYINT_SCALE = 0;
0079: public static final int TINYINT_MAXWIDTH = 1;
0080:
0081: // precision in number of bits
0082: public static final int DOUBLE_PRECISION = 52;
0083: // the ResultSetMetaData needs to have the precision for numeric data
0084: // in decimal digits, rather than number of bits, so need a separate constant.
0085: public static final int DOUBLE_PRECISION_IN_DIGITS = 15;
0086: public static final int DOUBLE_SCALE = 0;
0087: public static final int DOUBLE_MAXWIDTH = 8;
0088:
0089: // precision in number of bits
0090: public static final int REAL_PRECISION = 23;
0091: // the ResultSetMetaData needs to have the precision for numeric data
0092: // in decimal digits, rather than number of bits, so need a separate constant.
0093: public static final int REAL_PRECISION_IN_DIGITS = 7;
0094: public static final int REAL_SCALE = 0;
0095: public static final int REAL_MAXWIDTH = 4;
0096:
0097: public static final int DECIMAL_PRECISION = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;
0098: public static final int DECIMAL_SCALE = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;
0099: public static final int DECIMAL_MAXWIDTH = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE;
0100:
0101: public static final int BOOLEAN_MAXWIDTH = 1;
0102:
0103: public static final int CHAR_MAXWIDTH = Limits.DB2_CHAR_MAXWIDTH;
0104: public static final int VARCHAR_MAXWIDTH = Limits.DB2_VARCHAR_MAXWIDTH;
0105: public static final int LONGVARCHAR_MAXWIDTH = Limits.DB2_LONGVARCHAR_MAXWIDTH;
0106: public static final int NATIONAL_CHAR_MAXWIDTH = Integer.MAX_VALUE;
0107: public static final int NATIONAL_VARCHAR_MAXWIDTH = Integer.MAX_VALUE;
0108: public static final int NATIONAL_LONGVARCHAR_MAXWIDTH = Limits.DB2_LONGVARCHAR_MAXWIDTH;
0109: public static final int BIT_MAXWIDTH = Limits.DB2_CHAR_MAXWIDTH;
0110: public static final int VARBIT_MAXWIDTH = Limits.DB2_VARCHAR_MAXWIDTH;
0111: public static final int LONGVARBIT_MAXWIDTH = Limits.DB2_LONGVARCHAR_MAXWIDTH;
0112:
0113: // not supposed to be limited! 4096G should be ok(?), if Cloudscape can handle...
0114: public static final int BLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
0115: public static final int CLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
0116: public static final int NCLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
0117: public static final int XML_MAXWIDTH = Integer.MAX_VALUE;
0118:
0119: // Max width for datetime values is the length of the
0120: // string returned from a call to "toString()" on the
0121: // java.sql.Date, java.sql.Time, and java.sql.Timestamp
0122: // classes (the result of toString() on those classes
0123: // is defined by the JDBC API). This value is also
0124: // used as the "precision" for those types.
0125: public static final int DATE_MAXWIDTH = 10; // yyyy-mm-dd
0126: public static final int TIME_MAXWIDTH = 8; // hh:mm:ss
0127: public static final int TIMESTAMP_MAXWIDTH = 26; // yyyy-mm-dd hh:mm:ss.ffffff
0128:
0129: // Scale DOES exist for time values. For a TIMESTAMP value,
0130: // it's 6 ('ffffff'); for a TIME value, it's 0 (because there
0131: // are no fractional seconds). Note that date values do
0132: // not have a scale.
0133: public static final int TIME_SCALE = 0;
0134: public static final int TIMESTAMP_SCALE = 6;
0135:
0136: /* These define all the type names for SQL92 and JDBC
0137: * NOTE: boolean is SQL3
0138: */
0139: //public static final String BIT_NAME = "BIT";
0140: //public static final String VARBIT_NAME = "BIT VARYING";
0141: //public static final String LONGVARBIT_NAME = "LONG BIT VARYING";
0142: public static final String BIT_NAME = "CHAR () FOR BIT DATA";
0143: public static final String VARBIT_NAME = "VARCHAR () FOR BIT DATA";
0144: public static final String LONGVARBIT_NAME = "LONG VARCHAR FOR BIT DATA";
0145: public static final String TINYINT_NAME = "TINYINT";
0146: public static final String SMALLINT_NAME = "SMALLINT";
0147: public static final String INTEGER_NAME = "INTEGER";
0148: public static final String LONGINT_NAME = "BIGINT";
0149: public static final String FLOAT_NAME = "FLOAT";
0150: public static final String REAL_NAME = "REAL";
0151: public static final String DOUBLE_NAME = "DOUBLE";
0152: public static final String NUMERIC_NAME = "NUMERIC";
0153: public static final String DECIMAL_NAME = "DECIMAL";
0154: public static final String CHAR_NAME = "CHAR";
0155: public static final String VARCHAR_NAME = "VARCHAR";
0156: public static final String LONGVARCHAR_NAME = "LONG VARCHAR";
0157: public static final String DATE_NAME = "DATE";
0158: public static final String TIME_NAME = "TIME";
0159: public static final String TIMESTAMP_NAME = "TIMESTAMP";
0160: public static final String BINARY_NAME = "BINARY";
0161: public static final String VARBINARY_NAME = "VARBINARY";
0162: public static final String LONGVARBINARY_NAME = "LONGVARBINARY";
0163: public static final String BOOLEAN_NAME = "BOOLEAN";
0164: public static final String REF_NAME = "REF";
0165: public static final String NATIONAL_CHAR_NAME = "NATIONAL CHAR";
0166: public static final String NATIONAL_VARCHAR_NAME = "NATIONAL CHAR VARYING";
0167: public static final String NATIONAL_LONGVARCHAR_NAME = "LONG NVARCHAR";
0168: public static final String BLOB_NAME = "BLOB";
0169: public static final String CLOB_NAME = "CLOB";
0170: public static final String NCLOB_NAME = "NCLOB";
0171:
0172: // Following use of "XML" is per SQL/XML (2003) spec,
0173: // section "10.2 Type name determination".
0174: public static final String XML_NAME = "XML";
0175:
0176: // ARRAY and STRUCT are JDBC 2.0 data types that are not
0177: // supported by Derby.
0178: public static final String ARRAY_NAME = "ARRAY";
0179: public static final String STRUCT_NAME = "STRUCT";
0180:
0181: // DATALINK is a JDBC 3.0 data type. Not supported by Derby.
0182: public static final String DATALINK_NAME = "DATALINK";
0183:
0184: // ROWID and SQLXML are new types in JDBC 4.0. Not supported
0185: // by Derby.
0186: public static final String ROWID_NAME = "ROWID";
0187: public static final String SQLXML_NAME = "SQLXML";
0188:
0189: /**
0190: * The following constants define the type precedence hierarchy.
0191: */
0192: public static final int USER_PRECEDENCE = 1000;
0193:
0194: public static final int XML_PRECEDENCE = 180;
0195: public static final int BLOB_PRECEDENCE = 170;
0196: public static final int LONGVARBIT_PRECEDENCE = 160;
0197: public static final int VARBIT_PRECEDENCE = 150;
0198: public static final int BIT_PRECEDENCE = 140;
0199: public static final int BOOLEAN_PRECEDENCE = 130;
0200: public static final int TIME_PRECEDENCE = 120;
0201: public static final int TIMESTAMP_PRECEDENCE = 110;
0202: public static final int DATE_PRECEDENCE = 100;
0203: public static final int DOUBLE_PRECEDENCE = 90;
0204: public static final int REAL_PRECEDENCE = 80;
0205: public static final int DECIMAL_PRECEDENCE = 70;
0206: public static final int NUMERIC_PRECEDENCE = 69;
0207: public static final int LONGINT_PRECEDENCE = 60;
0208: public static final int INT_PRECEDENCE = 50;
0209: public static final int SMALLINT_PRECEDENCE = 40;
0210: public static final int TINYINT_PRECEDENCE = 30;
0211: public static final int REF_PRECEDENCE = 25;
0212: public static final int NATIONAL_LONGVARCHAR_PRECEDENCE = 18;
0213: public static final int NATIONAL_VARCHAR_PRECEDENCE = 17;
0214: public static final int NATIONAL_CHAR_PRECEDENCE = 16;
0215: public static final int CLOB_PRECEDENCE = 14;
0216: public static final int NCLOB_PRECEDENCE = 13;
0217: public static final int LONGVARCHAR_PRECEDENCE = 12;
0218: public static final int VARCHAR_PRECEDENCE = 10;
0219: public static final int CHAR_PRECEDENCE = 0;
0220:
0221: /*
0222: ** Static runtime fields for typeIds
0223: ** These are put here because the system needs them init time.
0224: */
0225: public static final TypeId BOOLEAN_ID = new TypeId(
0226: StoredFormatIds.BOOLEAN_TYPE_ID, new BaseTypeIdImpl(
0227: StoredFormatIds.BOOLEAN_TYPE_ID_IMPL));
0228: public static final TypeId INTEGER_ID = new TypeId(
0229: StoredFormatIds.INT_TYPE_ID, new BaseTypeIdImpl(
0230: StoredFormatIds.INT_TYPE_ID_IMPL));
0231: public static final TypeId CHAR_ID = new TypeId(
0232: StoredFormatIds.CHAR_TYPE_ID, new BaseTypeIdImpl(
0233: StoredFormatIds.CHAR_TYPE_ID_IMPL));
0234: /*
0235: ** Others are created on demand by the getBuiltInTypeId(int),
0236: ** if they are built-in (i.e.? Part of JDBC .Types),
0237: ** or by getBuiltInTypeId(string) if they are NATIONAL types or REF_NAME type.
0238: */
0239:
0240: private static TypeId TINYINT_ID;
0241: private static TypeId SMALLINT_ID;
0242: private static TypeId LONGINT_ID;
0243: private static TypeId REAL_ID;
0244: private static TypeId DOUBLE_ID;
0245: private static TypeId DECIMAL_ID;
0246: private static TypeId NUMERIC_ID;
0247: private static TypeId VARCHAR_ID;
0248: private static TypeId NATIONAL_CHAR_ID;
0249: private static TypeId NATIONAL_LONGVARCHAR_ID;
0250: private static TypeId NATIONAL_VARCHAR_ID;
0251: private static TypeId DATE_ID;
0252: private static TypeId TIME_ID;
0253: private static TypeId TIMESTAMP_ID;
0254: private static TypeId BIT_ID;
0255: private static TypeId VARBIT_ID;
0256: private static TypeId REF_ID;
0257: private static TypeId LONGVARCHAR_ID;
0258: private static TypeId LONGVARBIT_ID;
0259:
0260: private static TypeId BLOB_ID;
0261: private static TypeId CLOB_ID;
0262: private static TypeId NCLOB_ID;
0263: private static TypeId XML_ID;
0264:
0265: /**
0266: * Implementation of DECIMAL datatype for generating holders through getNull.
0267: * Set by the booted DataValueFactory implementation.
0268: */
0269: static DataValueDescriptor decimalImplementation;
0270:
0271: /*
0272: ** Static methods to obtain TypeIds
0273: */
0274: /**
0275: * Get a TypeId of the given JDBC type. This factory method is
0276: * intended to be used for built-in types. For user-defined types,
0277: * we will need a factory method that takes a Java type name.
0278: *
0279: * @param JDBCTypeId The JDBC Id of the type, as listed in
0280: * java.sql.Types
0281: *
0282: * @return The appropriate TypeId, or null if there is no such
0283: * TypeId.
0284: */
0285:
0286: public static TypeId getBuiltInTypeId(int JDBCTypeId) {
0287: TypeId ret = null;
0288:
0289: switch (JDBCTypeId) {
0290: case Types.TINYINT:
0291: ret = TINYINT_ID;
0292: if (ret == null)
0293: ret = TINYINT_ID = new TypeId(
0294: StoredFormatIds.TINYINT_TYPE_ID,
0295: new BaseTypeIdImpl(
0296: StoredFormatIds.TINYINT_TYPE_ID_IMPL));
0297: break;
0298:
0299: case Types.SMALLINT:
0300: ret = SMALLINT_ID;
0301: if (ret == null)
0302: ret = SMALLINT_ID = new TypeId(
0303: StoredFormatIds.SMALLINT_TYPE_ID,
0304: new BaseTypeIdImpl(
0305: StoredFormatIds.SMALLINT_TYPE_ID_IMPL));
0306: break;
0307:
0308: case Types.INTEGER:
0309: return INTEGER_ID;
0310:
0311: case Types.BIGINT:
0312: ret = LONGINT_ID;
0313: if (ret == null)
0314: ret = LONGINT_ID = new TypeId(
0315: StoredFormatIds.LONGINT_TYPE_ID,
0316: new BaseTypeIdImpl(
0317: StoredFormatIds.LONGINT_TYPE_ID_IMPL));
0318: break;
0319:
0320: case Types.REAL:
0321: ret = REAL_ID;
0322: if (ret == null)
0323: ret = REAL_ID = new TypeId(
0324: StoredFormatIds.REAL_TYPE_ID,
0325: new BaseTypeIdImpl(
0326: StoredFormatIds.REAL_TYPE_ID_IMPL));
0327: break;
0328:
0329: case Types.FLOAT:
0330: case Types.DOUBLE:
0331: ret = DOUBLE_ID;
0332: if (ret == null)
0333: ret = DOUBLE_ID = new TypeId(
0334: StoredFormatIds.DOUBLE_TYPE_ID,
0335: new BaseTypeIdImpl(
0336: StoredFormatIds.DOUBLE_TYPE_ID_IMPL));
0337: break;
0338:
0339: case Types.DECIMAL:
0340: ret = DECIMAL_ID;
0341: if (ret == null)
0342: ret = DECIMAL_ID = new TypeId(
0343: StoredFormatIds.DECIMAL_TYPE_ID,
0344: new DecimalTypeIdImpl());
0345: break;
0346:
0347: case Types.NUMERIC:
0348: ret = NUMERIC_ID;
0349: if (ret == null) {
0350: DecimalTypeIdImpl numericTypeIdImpl = new DecimalTypeIdImpl();
0351: numericTypeIdImpl.setNumericType();
0352: ret = NUMERIC_ID = new TypeId(
0353: StoredFormatIds.DECIMAL_TYPE_ID,
0354: numericTypeIdImpl);
0355: }
0356: break;
0357:
0358: case Types.CHAR:
0359: return CHAR_ID;
0360:
0361: case Types.VARCHAR:
0362: ret = VARCHAR_ID;
0363: if (ret == null)
0364: ret = VARCHAR_ID = new TypeId(
0365: StoredFormatIds.VARCHAR_TYPE_ID,
0366: new BaseTypeIdImpl(
0367: StoredFormatIds.VARCHAR_TYPE_ID_IMPL));
0368: break;
0369:
0370: case Types.DATE:
0371: ret = DATE_ID;
0372: if (ret == null)
0373: ret = DATE_ID = new TypeId(
0374: StoredFormatIds.DATE_TYPE_ID,
0375: new BaseTypeIdImpl(
0376: StoredFormatIds.DATE_TYPE_ID_IMPL));
0377: break;
0378:
0379: case Types.TIME:
0380: ret = TIME_ID;
0381: if (ret == null)
0382: ret = TIME_ID = new TypeId(
0383: StoredFormatIds.TIME_TYPE_ID,
0384: new BaseTypeIdImpl(
0385: StoredFormatIds.TIME_TYPE_ID_IMPL));
0386: break;
0387:
0388: case Types.TIMESTAMP:
0389: ret = TIMESTAMP_ID;
0390: if (ret == null)
0391: ret = TIMESTAMP_ID = new TypeId(
0392: StoredFormatIds.TIMESTAMP_TYPE_ID,
0393: new BaseTypeIdImpl(
0394: StoredFormatIds.TIMESTAMP_TYPE_ID_IMPL));
0395: break;
0396: case Types.BIT:
0397: case JDBC30Translation.SQL_TYPES_BOOLEAN:
0398: return BOOLEAN_ID;
0399:
0400: case Types.BINARY:
0401: ret = BIT_ID;
0402: if (ret == null)
0403: ret = BIT_ID = new TypeId(StoredFormatIds.BIT_TYPE_ID,
0404: new BaseTypeIdImpl(
0405: StoredFormatIds.BIT_TYPE_ID_IMPL));
0406: break;
0407:
0408: case Types.VARBINARY:
0409: ret = VARBIT_ID;
0410: if (ret == null)
0411: ret = VARBIT_ID = new TypeId(
0412: StoredFormatIds.VARBIT_TYPE_ID,
0413: new BaseTypeIdImpl(
0414: StoredFormatIds.VARBIT_TYPE_ID_IMPL));
0415: break;
0416:
0417: case Types.LONGVARBINARY:
0418: ret = LONGVARBIT_ID;
0419: if (ret == null)
0420: ret = LONGVARBIT_ID = new TypeId(
0421: StoredFormatIds.LONGVARBIT_TYPE_ID,
0422: new BaseTypeIdImpl(
0423: StoredFormatIds.LONGVARBIT_TYPE_ID_IMPL));
0424: break;
0425:
0426: case Types.LONGVARCHAR:
0427: ret = LONGVARCHAR_ID;
0428: if (ret == null)
0429: ret = LONGVARCHAR_ID = new TypeId(
0430: StoredFormatIds.LONGVARCHAR_TYPE_ID,
0431: new BaseTypeIdImpl(
0432: StoredFormatIds.LONGVARCHAR_TYPE_ID_IMPL));
0433: break;
0434:
0435: case JDBC20Translation.SQL_TYPES_BLOB:
0436: ret = BLOB_ID;
0437: if (ret == null)
0438: ret = BLOB_ID = new TypeId(
0439: StoredFormatIds.BLOB_TYPE_ID,
0440: new BaseTypeIdImpl(
0441: StoredFormatIds.BLOB_TYPE_ID_IMPL));
0442: break;
0443:
0444: case JDBC20Translation.SQL_TYPES_CLOB:
0445: ret = CLOB_ID;
0446: if (ret == null)
0447: ret = CLOB_ID = new TypeId(
0448: StoredFormatIds.CLOB_TYPE_ID,
0449: new BaseTypeIdImpl(
0450: StoredFormatIds.CLOB_TYPE_ID_IMPL));
0451: break;
0452:
0453: // XML is not a JDBC type, so we have to check for our
0454: // internal XML type.
0455: case StoredFormatIds.XML_TYPE_ID:
0456: ret = XML_ID;
0457: if (ret == null)
0458: ret = XML_ID = new TypeId(StoredFormatIds.XML_TYPE_ID,
0459: new BaseTypeIdImpl(
0460: StoredFormatIds.XML_TYPE_ID_IMPL));
0461: break;
0462: }
0463: return ret;
0464: }
0465:
0466: public static TypeId getUserDefinedTypeId(String className,
0467: boolean delimitedIdentifier) {
0468: return new TypeId(StoredFormatIds.USERDEFINED_TYPE_ID_V3,
0469: new UserDefinedTypeIdImpl(className),
0470: delimitedIdentifier);
0471: }
0472:
0473: /**
0474: * Get a TypeId for the class that corresponds to the given
0475: * Java type name.
0476: *
0477: * @param javaTypeName The name of the Java type
0478: *
0479: * @return A TypeId for the SQL type that corresponds to
0480: * the Java type, null if there is no corresponding type.
0481: */
0482: public static TypeId getSQLTypeForJavaType(String javaTypeName) {
0483: if (javaTypeName.equals("java.lang.Boolean")
0484: || javaTypeName.equals("boolean")) {
0485: return TypeId.BOOLEAN_ID;
0486: } else if (javaTypeName.equals("byte[]")) {
0487: return getBuiltInTypeId(Types.VARBINARY);
0488: } else if (javaTypeName.equals("java.lang.String")) {
0489: return getBuiltInTypeId(Types.VARCHAR);
0490: } else if (javaTypeName.equals("java.lang.Integer")
0491: || javaTypeName.equals("int")) {
0492: return TypeId.INTEGER_ID;
0493: } else if (javaTypeName.equals("byte")) {
0494: return getBuiltInTypeId(Types.TINYINT);
0495: } else if (javaTypeName.equals("short")) {
0496: return getBuiltInTypeId(Types.SMALLINT);
0497: } else if (javaTypeName.equals("java.lang.Long")
0498: || javaTypeName.equals("long")) {
0499: return getBuiltInTypeId(Types.BIGINT);
0500: } else if (javaTypeName.equals("java.lang.Float")
0501: || javaTypeName.equals("float")) {
0502: return getBuiltInTypeId(Types.REAL);
0503: } else if (javaTypeName.equals("java.lang.Double")
0504: || javaTypeName.equals("double")) {
0505: return getBuiltInTypeId(Types.DOUBLE);
0506: } else if (javaTypeName.equals("java.math.BigDecimal")) {
0507: return getBuiltInTypeId(Types.DECIMAL);
0508: } else if (javaTypeName.equals("java.sql.Date")) {
0509: return getBuiltInTypeId(Types.DATE);
0510: } else if (javaTypeName.equals("java.sql.Time")) {
0511: return getBuiltInTypeId(Types.TIME);
0512: } else if (javaTypeName.equals("java.sql.Timestamp")) {
0513: return getBuiltInTypeId(Types.TIMESTAMP);
0514: } else if (javaTypeName.equals("java.sql.Blob")) {
0515: return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_BLOB);
0516: } else if (javaTypeName.equals("java.sql.Clob")) {
0517: return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);
0518: } else if (javaTypeName
0519: .equals("org.apache.derby.iapi.types.XML")) {
0520: return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);
0521: } else {
0522: /*
0523: ** If it's a Java primitive type, return null to indicate that
0524: ** there is no corresponding SQL type (all the Java primitive
0525: ** types that have corresponding SQL types are handled above).
0526: **
0527: ** There is only one primitive type not mentioned above, char.
0528: */
0529: if (javaTypeName.equals("char")) {
0530: return null;
0531: }
0532:
0533: /*
0534: ** It's a non-primitive type (a class) that does not correspond
0535: ** to a SQL built-in type, so treat it as a user-defined type.
0536: */
0537: return TypeId.getUserDefinedTypeId(javaTypeName, false);
0538: }
0539: }
0540:
0541: public static TypeId getBuiltInTypeId(String SQLTypeName) {
0542:
0543: if (SQLTypeName.equals(TypeId.BOOLEAN_NAME)) {
0544: return TypeId.BOOLEAN_ID;
0545: }
0546: if (SQLTypeName.equals(TypeId.CHAR_NAME)) {
0547: return TypeId.CHAR_ID;
0548: }
0549: if (SQLTypeName.equals(TypeId.DATE_NAME)) {
0550: return getBuiltInTypeId(Types.DATE);
0551: }
0552: if (SQLTypeName.equals(TypeId.DOUBLE_NAME)) {
0553: return getBuiltInTypeId(Types.DOUBLE);
0554: }
0555: if (SQLTypeName.equals(TypeId.FLOAT_NAME)) {
0556: return getBuiltInTypeId(Types.DOUBLE);
0557: }
0558: if (SQLTypeName.equals(TypeId.INTEGER_NAME)) {
0559: return TypeId.INTEGER_ID;
0560: }
0561: if (SQLTypeName.equals(TypeId.LONGINT_NAME)) {
0562: return getBuiltInTypeId(Types.BIGINT);
0563: }
0564: if (SQLTypeName.equals(TypeId.REAL_NAME)) {
0565: return getBuiltInTypeId(Types.REAL);
0566: }
0567: if (SQLTypeName.equals(TypeId.SMALLINT_NAME)) {
0568: return getBuiltInTypeId(Types.SMALLINT);
0569: }
0570: if (SQLTypeName.equals(TypeId.TIME_NAME)) {
0571: return getBuiltInTypeId(Types.TIME);
0572: }
0573: if (SQLTypeName.equals(TypeId.TIMESTAMP_NAME)) {
0574: return getBuiltInTypeId(Types.TIMESTAMP);
0575: }
0576: if (SQLTypeName.equals(TypeId.VARCHAR_NAME)) {
0577: return getBuiltInTypeId(Types.VARCHAR);
0578: }
0579: if (SQLTypeName.equals(TypeId.BIT_NAME)) {
0580: return getBuiltInTypeId(Types.BINARY);
0581: }
0582: if (SQLTypeName.equals(TypeId.VARBIT_NAME)) {
0583: return getBuiltInTypeId(Types.VARBINARY);
0584: }
0585: if (SQLTypeName.equals(TypeId.TINYINT_NAME)) {
0586: return getBuiltInTypeId(Types.TINYINT);
0587: }
0588: if (SQLTypeName.equals(TypeId.DECIMAL_NAME)) {
0589: return getBuiltInTypeId(Types.DECIMAL);
0590: }
0591: if (SQLTypeName.equals(TypeId.NUMERIC_NAME)) {
0592: return getBuiltInTypeId(Types.NUMERIC);
0593: }
0594: if (SQLTypeName.equals(TypeId.LONGVARCHAR_NAME)) {
0595: return getBuiltInTypeId(Types.LONGVARCHAR);
0596: }
0597: if (SQLTypeName.equals(TypeId.LONGVARBIT_NAME)) {
0598: return getBuiltInTypeId(Types.LONGVARBINARY);
0599: }
0600: if (SQLTypeName.equals(TypeId.BLOB_NAME)) {
0601: return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_BLOB);
0602: }
0603: if (SQLTypeName.equals(TypeId.CLOB_NAME)) {
0604: return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);
0605: }
0606: if (SQLTypeName.equals(TypeId.XML_NAME)) {
0607: return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);
0608: }
0609:
0610: TypeId ret = null;
0611:
0612: // Types defined below here are SQL types and non-JDBC types that are supported by Cloudscape
0613: if (SQLTypeName.equals(TypeId.NCLOB_NAME)) {
0614: ret = NCLOB_ID;
0615: if (ret == null)
0616: ret = NCLOB_ID = new TypeId(
0617: StoredFormatIds.NCLOB_TYPE_ID,
0618: new BaseTypeIdImpl(
0619: StoredFormatIds.NCLOB_TYPE_ID_IMPL));
0620: } else if (SQLTypeName.equals(TypeId.NATIONAL_CHAR_NAME)) {
0621: ret = NATIONAL_CHAR_ID;
0622: if (ret == null)
0623: ret = NATIONAL_CHAR_ID = new TypeId(
0624: StoredFormatIds.NATIONAL_CHAR_TYPE_ID,
0625: new BaseTypeIdImpl(
0626: StoredFormatIds.NATIONAL_CHAR_TYPE_ID_IMPL));
0627:
0628: } else if (SQLTypeName.equals(TypeId.NATIONAL_LONGVARCHAR_NAME)) {
0629: ret = NATIONAL_LONGVARCHAR_ID;
0630: if (ret == null)
0631: ret = NATIONAL_LONGVARCHAR_ID = new TypeId(
0632: StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID,
0633: new BaseTypeIdImpl(
0634: StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID_IMPL));
0635:
0636: } else if (SQLTypeName.equals(TypeId.NATIONAL_VARCHAR_NAME)) {
0637: ret = NATIONAL_VARCHAR_ID;
0638: if (ret == null)
0639: ret = NATIONAL_VARCHAR_ID = new TypeId(
0640: StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID,
0641: new BaseTypeIdImpl(
0642: StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID_IMPL));
0643:
0644: } else if (SQLTypeName.equals(TypeId.REF_NAME)) {
0645: ret = REF_ID;
0646: if (ret == null)
0647: ret = REF_ID = new TypeId(StoredFormatIds.REF_TYPE_ID,
0648: new BaseTypeIdImpl(
0649: StoredFormatIds.REF_TYPE_ID_IMPL));
0650: }
0651: return ret;
0652: }
0653:
0654: /*
0655: ** Instance fields and methods
0656: */
0657:
0658: private BaseTypeIdImpl baseTypeId;
0659: private int formatId;
0660:
0661: /* Set in setTypeIdSpecificInstanceVariables() as needed */
0662: private boolean classNameWasDelimitedIdentifier;
0663: private boolean isBitTypeId;
0664: private boolean isLOBTypeId;
0665: private boolean isBooleanTypeId;
0666: private boolean isConcatableTypeId;
0667: private boolean isDecimalTypeId;
0668: private boolean isLongConcatableTypeId;
0669: private boolean isNumericTypeId;
0670: private boolean isRefTypeId;
0671: private boolean isStringTypeId;
0672: private boolean isFloatingPointTypeId;
0673: private boolean isRealTypeId;
0674: private boolean isDateTimeTimeStampTypeId;
0675: private boolean isUserDefinedTypeId;
0676: private int maxPrecision;
0677: private int maxScale;
0678: private int typePrecedence;
0679: private String javaTypeName;
0680: private int maxMaxWidth;
0681:
0682: /**
0683: * 1 argmument constructor. Needed for Formatable interface to work.
0684: *
0685: * @param formatId Format id of specific type id.
0686: */
0687:
0688: public TypeId(int formatId) {
0689: this .formatId = formatId;
0690: setTypeIdSpecificInstanceVariables();
0691: }
0692:
0693: /**
0694: * Constructor for a TypeId
0695: *
0696: * @param formatId Format id of specific type id.
0697: * @param baseTypeId The Base type id
0698: */
0699: public TypeId(int formatId, BaseTypeIdImpl baseTypeId) {
0700: this .formatId = formatId;
0701: this .baseTypeId = baseTypeId;
0702: setTypeIdSpecificInstanceVariables();
0703: }
0704:
0705: /**
0706: * Constructor for a TypeId for user defined types
0707: *
0708: * @param formatId Format id of specific type id.
0709: * @param baseTypeId The Base type id
0710: * @param classNameWasDelimitedIdentifier Whether or not the class name
0711: * was a delimited identifier
0712: */
0713: public TypeId(int formatId, BaseTypeIdImpl baseTypeId,
0714: boolean classNameWasDelimitedIdentifier) {
0715: this .formatId = formatId;
0716: this .baseTypeId = baseTypeId;
0717: this .classNameWasDelimitedIdentifier = classNameWasDelimitedIdentifier;
0718: setTypeIdSpecificInstanceVariables();
0719: }
0720:
0721: /**
0722: * we want equals to say if these are the same type id or not.
0723: */
0724: public boolean equals(Object that) {
0725: if (that instanceof TypeId)
0726: return this .getSQLTypeName().equals(
0727: ((TypeId) that).getSQLTypeName());
0728: else
0729: return false;
0730: }
0731:
0732: /*
0733: Hashcode which works with equals.
0734: */
0735: public int hashCode() {
0736: return this .getSQLTypeName().hashCode();
0737: }
0738:
0739: private void setTypeIdSpecificInstanceVariables() {
0740: switch (formatId) {
0741: case StoredFormatIds.BIT_TYPE_ID:
0742: typePrecedence = BIT_PRECEDENCE;
0743: javaTypeName = "byte[]";
0744: maxMaxWidth = TypeId.BIT_MAXWIDTH;
0745: isBitTypeId = true;
0746: isConcatableTypeId = true;
0747: break;
0748:
0749: case StoredFormatIds.BOOLEAN_TYPE_ID:
0750: typePrecedence = BOOLEAN_PRECEDENCE;
0751: javaTypeName = "java.lang.Boolean";
0752: maxMaxWidth = TypeId.BOOLEAN_MAXWIDTH;
0753: isBooleanTypeId = true;
0754: break;
0755:
0756: case StoredFormatIds.CHAR_TYPE_ID:
0757: typePrecedence = CHAR_PRECEDENCE;
0758: javaTypeName = "java.lang.String";
0759: maxMaxWidth = TypeId.CHAR_MAXWIDTH;
0760: isStringTypeId = true;
0761: isConcatableTypeId = true;
0762: break;
0763:
0764: case StoredFormatIds.DATE_TYPE_ID:
0765: typePrecedence = DATE_PRECEDENCE;
0766: javaTypeName = "java.sql.Date";
0767: maxMaxWidth = TypeId.DATE_MAXWIDTH;
0768: maxPrecision = TypeId.DATE_MAXWIDTH;
0769: isDateTimeTimeStampTypeId = true;
0770: break;
0771:
0772: case StoredFormatIds.DECIMAL_TYPE_ID:
0773: maxPrecision = TypeId.DECIMAL_PRECISION;
0774: maxScale = TypeId.DECIMAL_SCALE;
0775: typePrecedence = DECIMAL_PRECEDENCE;
0776: javaTypeName = "java.math.BigDecimal";
0777: maxMaxWidth = TypeId.DECIMAL_MAXWIDTH;
0778: isDecimalTypeId = true;
0779: isNumericTypeId = true;
0780: break;
0781:
0782: case StoredFormatIds.DOUBLE_TYPE_ID:
0783: maxPrecision = TypeId.DOUBLE_PRECISION;
0784: maxScale = TypeId.DOUBLE_SCALE;
0785: typePrecedence = DOUBLE_PRECEDENCE;
0786: javaTypeName = "java.lang.Double";
0787: maxMaxWidth = TypeId.DOUBLE_MAXWIDTH;
0788: isNumericTypeId = true;
0789: isFloatingPointTypeId = true;
0790: break;
0791:
0792: case StoredFormatIds.INT_TYPE_ID:
0793: maxPrecision = TypeId.INT_PRECISION;
0794: maxScale = TypeId.INT_SCALE;
0795: typePrecedence = INT_PRECEDENCE;
0796: javaTypeName = "java.lang.Integer";
0797: maxMaxWidth = TypeId.INT_MAXWIDTH;
0798: isNumericTypeId = true;
0799: break;
0800:
0801: case StoredFormatIds.LONGINT_TYPE_ID:
0802: maxPrecision = TypeId.LONGINT_PRECISION;
0803: maxScale = TypeId.LONGINT_SCALE;
0804: typePrecedence = LONGINT_PRECEDENCE;
0805: javaTypeName = "java.lang.Long";
0806: maxMaxWidth = TypeId.LONGINT_MAXWIDTH;
0807: isNumericTypeId = true;
0808: break;
0809:
0810: case StoredFormatIds.LONGVARBIT_TYPE_ID:
0811: typePrecedence = LONGVARBIT_PRECEDENCE;
0812: javaTypeName = "byte[]";
0813: maxMaxWidth = TypeId.LONGVARBIT_MAXWIDTH;
0814: isBitTypeId = true;
0815: isConcatableTypeId = true;
0816: isLongConcatableTypeId = true;
0817: break;
0818:
0819: case StoredFormatIds.LONGVARCHAR_TYPE_ID:
0820: typePrecedence = LONGVARCHAR_PRECEDENCE;
0821: javaTypeName = "java.lang.String";
0822: maxMaxWidth = TypeId.LONGVARCHAR_MAXWIDTH;
0823: isStringTypeId = true;
0824: isConcatableTypeId = true;
0825: isLongConcatableTypeId = true;
0826: break;
0827:
0828: case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
0829: typePrecedence = NATIONAL_CHAR_PRECEDENCE;
0830: javaTypeName = "java.lang.String";
0831: maxMaxWidth = TypeId.NATIONAL_CHAR_MAXWIDTH;
0832: isStringTypeId = true;
0833: isConcatableTypeId = true;
0834: break;
0835:
0836: case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
0837: typePrecedence = NATIONAL_LONGVARCHAR_PRECEDENCE;
0838: javaTypeName = "java.lang.String";
0839: maxMaxWidth = TypeId.NATIONAL_LONGVARCHAR_MAXWIDTH;
0840: isStringTypeId = true;
0841: isConcatableTypeId = true;
0842: isLongConcatableTypeId = true;
0843: break;
0844:
0845: case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
0846: typePrecedence = NATIONAL_VARCHAR_PRECEDENCE;
0847: javaTypeName = "java.lang.String";
0848: maxMaxWidth = TypeId.NATIONAL_VARCHAR_MAXWIDTH;
0849: isStringTypeId = true;
0850: isConcatableTypeId = true;
0851: break;
0852:
0853: case StoredFormatIds.REAL_TYPE_ID:
0854: maxPrecision = TypeId.REAL_PRECISION;
0855: maxScale = TypeId.REAL_SCALE;
0856: typePrecedence = REAL_PRECEDENCE;
0857: javaTypeName = "java.lang.Float";
0858: maxMaxWidth = TypeId.REAL_MAXWIDTH;
0859: isNumericTypeId = true;
0860: isRealTypeId = true;
0861: isFloatingPointTypeId = true;
0862: break;
0863:
0864: case StoredFormatIds.REF_TYPE_ID:
0865: typePrecedence = REF_PRECEDENCE;
0866: isRefTypeId = true;
0867: break;
0868:
0869: case StoredFormatIds.SMALLINT_TYPE_ID:
0870: maxPrecision = TypeId.SMALLINT_PRECISION;
0871: maxScale = TypeId.SMALLINT_SCALE;
0872: typePrecedence = SMALLINT_PRECEDENCE;
0873: javaTypeName = "java.lang.Integer";
0874: maxMaxWidth = TypeId.SMALLINT_MAXWIDTH;
0875: isNumericTypeId = true;
0876: break;
0877:
0878: case StoredFormatIds.TIME_TYPE_ID:
0879: typePrecedence = TIME_PRECEDENCE;
0880: javaTypeName = "java.sql.Time";
0881: maxScale = TypeId.TIME_SCALE;
0882: maxMaxWidth = TypeId.TIME_MAXWIDTH;
0883: maxPrecision = TypeId.TIME_MAXWIDTH;
0884: isDateTimeTimeStampTypeId = true;
0885: break;
0886:
0887: case StoredFormatIds.TIMESTAMP_TYPE_ID:
0888: typePrecedence = TIMESTAMP_PRECEDENCE;
0889: javaTypeName = "java.sql.Timestamp";
0890: maxScale = TypeId.TIMESTAMP_SCALE;
0891: maxMaxWidth = TypeId.TIMESTAMP_MAXWIDTH;
0892: maxPrecision = TypeId.TIMESTAMP_MAXWIDTH;
0893: isDateTimeTimeStampTypeId = true;
0894: break;
0895:
0896: case StoredFormatIds.TINYINT_TYPE_ID:
0897: maxPrecision = TypeId.TINYINT_PRECISION;
0898: maxScale = TypeId.TINYINT_SCALE;
0899: typePrecedence = TINYINT_PRECEDENCE;
0900: javaTypeName = "java.lang.Integer";
0901: maxMaxWidth = TypeId.TINYINT_MAXWIDTH;
0902: isNumericTypeId = true;
0903: break;
0904:
0905: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
0906: if (baseTypeId != null) {
0907: setUserTypeIdInfo();
0908: } else {
0909: typePrecedence = USER_PRECEDENCE;
0910: }
0911: maxMaxWidth = -1;
0912: isUserDefinedTypeId = true;
0913: break;
0914:
0915: case StoredFormatIds.VARBIT_TYPE_ID:
0916: typePrecedence = VARBIT_PRECEDENCE;
0917: javaTypeName = "byte[]";
0918: maxMaxWidth = TypeId.VARBIT_MAXWIDTH;
0919: isBitTypeId = true;
0920: isConcatableTypeId = true;
0921: break;
0922:
0923: case StoredFormatIds.BLOB_TYPE_ID:
0924: typePrecedence = BLOB_PRECEDENCE;
0925: javaTypeName = "java.sql.Blob";
0926: maxMaxWidth = TypeId.BLOB_MAXWIDTH;
0927: isBitTypeId = true;
0928: isConcatableTypeId = true;
0929: isLongConcatableTypeId = true; // ??
0930: isLOBTypeId = true;
0931: break;
0932:
0933: case StoredFormatIds.VARCHAR_TYPE_ID:
0934: typePrecedence = VARCHAR_PRECEDENCE;
0935: javaTypeName = "java.lang.String";
0936: maxMaxWidth = TypeId.VARCHAR_MAXWIDTH;
0937: isStringTypeId = true;
0938: isConcatableTypeId = true;
0939: break;
0940:
0941: case StoredFormatIds.CLOB_TYPE_ID:
0942: typePrecedence = CLOB_PRECEDENCE;
0943: javaTypeName = "java.sql.Clob";
0944: maxMaxWidth = TypeId.CLOB_MAXWIDTH;
0945: isStringTypeId = true;
0946: isConcatableTypeId = true;
0947: isLongConcatableTypeId = true; // ??
0948: isLOBTypeId = true;
0949: break;
0950:
0951: case StoredFormatIds.NCLOB_TYPE_ID:
0952: typePrecedence = NCLOB_PRECEDENCE;
0953: javaTypeName = "java.sql.Clob";
0954: maxMaxWidth = TypeId.NCLOB_MAXWIDTH;
0955: isStringTypeId = true;
0956: isConcatableTypeId = true;
0957: isLongConcatableTypeId = true; // ??
0958: isLOBTypeId = true;
0959: break;
0960:
0961: case StoredFormatIds.XML_TYPE_ID:
0962:
0963: typePrecedence = XML_PRECEDENCE;
0964: javaTypeName = "org.apache.derby.iapi.types.XML";
0965: maxMaxWidth = TypeId.XML_MAXWIDTH;
0966:
0967: // We set this to true in order to disallow use
0968: // of the XML datatype for procedure/function args.
0969: isLongConcatableTypeId = true;
0970: break;
0971:
0972: }
0973: }
0974:
0975: /**
0976: * JDBC has its own idea of type identifiers which is different from
0977: * the Cloudscape internal type ids. The JDBC type ids are defined
0978: * as public final static ints in java.sql.Types. This method translates
0979: * a Cloudscape internal TypeId to a JDBC type id. For java objects this
0980: * returns JAVA_OBJECT in Java2 and OTHER in JDK 1.1. For Boolean datatypes,
0981: * this returns Type.BOOLEAN in JDK1.4 and Type.BIT for jdks prior to 1.4
0982: *
0983: * @return The JDBC type Id for this type
0984: */
0985: public final int getJDBCTypeId() {
0986: return baseTypeId.getJDBCTypeId();
0987: }
0988:
0989: /**
0990: * Returns the SQL name of the datatype. If it is a user-defined type,
0991: * it returns the full Java path name for the datatype, meaning the
0992: * dot-separated path including the package names.
0993: *
0994: * @return A String containing the SQL name of this type.
0995: */
0996: public String getSQLTypeName() {
0997: return baseTypeId.getSQLTypeName();
0998: }
0999:
1000: /**
1001: * Tell whether this is a built-in type.
1002: * NOTE: There are 3 "classes" of types:
1003: * built-in - system provided types which are implemented internally
1004: * (int, smallint, etc.)
1005: * system built-in - system provided types, independent of implementation
1006: * (date, time, etc.)
1007: * user types - types implemented outside of the system
1008: * (java.lang.Integer, asdf.asdf.asdf, etc.)
1009: *
1010: * @return true for built-in types, false for user-defined types.
1011: */
1012: public final boolean userType() {
1013: return baseTypeId.userType();
1014: }
1015:
1016: /**
1017: * Get the maximum precision of the type. For types with variable
1018: * precision, this is an arbitrary high precision.
1019: *
1020: * @return The maximum precision of the type
1021: */
1022: public int getMaximumPrecision() {
1023: return maxPrecision;
1024: }
1025:
1026: /**
1027: * Get the maximum scale of the type. For types with variable scale,
1028: * this is an arbitrary high scale.
1029: *
1030: * @return The maximum scale of the type
1031: */
1032: public int getMaximumScale() {
1033: return maxScale;
1034: }
1035:
1036: /**
1037: * Set the nested BaseTypeId in this TypeId.
1038: */
1039: public void setNestedTypeId(BaseTypeIdImpl typeId) {
1040: baseTypeId = typeId;
1041: switch (formatId) {
1042: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
1043: setUserTypeIdInfo();
1044: }
1045: }
1046:
1047: private void setUserTypeIdInfo() {
1048: UserDefinedTypeIdImpl baseUserTypeId = (UserDefinedTypeIdImpl) baseTypeId;
1049: typePrecedence = USER_PRECEDENCE;
1050: javaTypeName = baseUserTypeId.getClassName();
1051: }
1052:
1053: /**
1054: * For user types, tell whether or not the class name was a
1055: * delimited identifier. For all other types, return false.
1056: *
1057: * @return Whether or not the class name was a delimited identifier.
1058: */
1059: public boolean getClassNameWasDelimitedIdentifier() {
1060: return classNameWasDelimitedIdentifier;
1061: }
1062:
1063: /**
1064: * Does this TypeId represent a TypeId for a StringDataType.
1065: *
1066: * @return Whether or not this TypeId represents a TypeId for a StringDataType.
1067: */
1068: public boolean isStringTypeId() {
1069: return isStringTypeId;
1070: }
1071:
1072: /**
1073: * Is this a TypeId for DATE/TIME/TIMESTAMP
1074: *
1075: * @return true if this is a DATE/TIME/TIMESTAMP
1076: */
1077: public boolean isDateTimeTimeStampTypeId() {
1078: return isDateTimeTimeStampTypeId;
1079: }
1080:
1081: /**
1082: * Is this a TypeId for REAL
1083: *
1084: * @return true if this is a REAL
1085: */
1086: public boolean isRealTypeId() {
1087: return isRealTypeId;
1088: }
1089:
1090: /**
1091: * Is this a TypeId for floating point (REAL/DOUBLE)
1092: *
1093: * @return true if this is a REAL or DOUBLE
1094: */
1095: public boolean isFloatingPointTypeId() {
1096: return isFloatingPointTypeId;
1097: }
1098:
1099: /**
1100: * Is this a TypeId for DOUBLE
1101: *
1102: * @return true if this is a DOUBLE
1103: */
1104: public boolean isDoubleTypeId() {
1105: return isFloatingPointTypeId && (!isRealTypeId);
1106: }
1107:
1108: /**
1109: * Is this a fixed string type?
1110: * @return true if this is CHAR or NCHAR
1111: */
1112: public boolean isFixedStringTypeId() {
1113: return ((formatId == StoredFormatIds.CHAR_TYPE_ID) || (formatId == StoredFormatIds.NATIONAL_CHAR_TYPE_ID));
1114: }
1115:
1116: /**
1117: *Is this a Clob?
1118: * @return true if this is CLOB or NCLOB
1119: */
1120: public boolean isClobTypeId() {
1121: return ((formatId == StoredFormatIds.CLOB_TYPE_ID) || (formatId == StoredFormatIds.NCLOB_TYPE_ID));
1122: }
1123:
1124: /**
1125: *Is this a Blob?
1126: * @return true if this is BLOB
1127: */
1128: public boolean isBlobTypeId() {
1129: return ((formatId == StoredFormatIds.BLOB_TYPE_ID));
1130: }
1131:
1132: /**
1133: *Is this a LongVarchar?
1134: * @return true if this is LongVarchar
1135: */
1136: public boolean isLongVarcharTypeId() {
1137: return ((formatId == StoredFormatIds.LONGVARCHAR_TYPE_ID) || (formatId == StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID));
1138: }
1139:
1140: /**
1141: * Is this DATE/TIME or TIMESTAMP?
1142: *
1143: * @return true if this DATE/TIME or TIMESTAMP
1144: */
1145: public boolean isDateTimeTimeStampTypeID() {
1146: return ((formatId == StoredFormatIds.DATE_TYPE_ID)
1147: || (formatId == StoredFormatIds.TIME_TYPE_ID) || (formatId == StoredFormatIds.TIMESTAMP_TYPE_ID));
1148: }
1149:
1150: /**
1151: Does this type id represent a national character string.
1152: If this returns true then isStringTypeId will also return true.
1153: */
1154: public boolean isNationalStringTypeId() {
1155: switch (formatId) {
1156: default:
1157: return false;
1158:
1159: case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
1160: case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
1161: case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
1162: case StoredFormatIds.NCLOB_TYPE_ID:
1163: return true;
1164:
1165: }
1166: }
1167:
1168: /**
1169: *Is this an XML doc?
1170: * @return true if this is XML
1171: */
1172: public boolean isXMLTypeId() {
1173: return (formatId == StoredFormatIds.XML_TYPE_ID);
1174: }
1175:
1176: /**
1177: * Tell whether this type is orderable, that is, can participate
1178: * in comparisons.
1179: *
1180: * @param cf A ClassFactory
1181: *
1182: * @return true for orderable types, false for non-orderable types.
1183: */
1184: public boolean orderable(ClassFactory cf) {
1185: boolean orderable;
1186: switch (formatId) {
1187: // cmp not allowed, indexing not allowed
1188: case StoredFormatIds.BLOB_TYPE_ID:
1189: case StoredFormatIds.CLOB_TYPE_ID:
1190: case StoredFormatIds.NCLOB_TYPE_ID:
1191: case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
1192: case StoredFormatIds.LONGVARCHAR_TYPE_ID:
1193: case StoredFormatIds.XML_TYPE_ID:
1194: case StoredFormatIds.LONGVARBIT_TYPE_ID:
1195: return false;
1196:
1197: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
1198: /* Is this type orderable? */
1199:
1200: // For user java classes we are orderable if we
1201: // implement java.lang.Orderable (JDK1.2) or
1202: // have a int compareTo(Object) method (JDK1.1 or JDK1.2)
1203: UserDefinedTypeIdImpl baseUserTypeId = (UserDefinedTypeIdImpl) baseTypeId;
1204:
1205: String className = baseUserTypeId.getClassName();
1206:
1207: try {
1208: Class c = cf.getClassInspector().getClass(className);
1209: orderable = java.lang.Comparable.class
1210: .isAssignableFrom(c);
1211: } catch (ClassNotFoundException cnfe) {
1212: orderable = false;
1213: }
1214: break;
1215:
1216: default:
1217: orderable = true;
1218: }
1219:
1220: return orderable;
1221: }
1222:
1223: /**
1224: * Each built-in type in JSQL has a precedence. This precedence determines
1225: * how to do type promotion when using binary operators. For example, float
1226: * has a higher precedence than int, so when adding an int to a float, the
1227: * result type is float.
1228: *
1229: * The precedence for some types is arbitrary. For example, it doesn't
1230: * matter what the precedence of the boolean type is, since it can't be
1231: * mixed with other types. But the precedence for the number types is
1232: * critical. The SQL standard requires that exact numeric types be
1233: * promoted to approximate numeric when one operator uses both. Also,
1234: * the precedence is arranged so that one will not lose precision when
1235: * promoting a type.
1236: * NOTE: char, varchar, and longvarchar must appear at the bottom of
1237: * the hierarchy, but above USER_PRECEDENCE, since we allow the implicit
1238: * conversion of those types to any other built-in system type.
1239: *
1240: * @return The precedence of this type.
1241: */
1242: public int typePrecedence() {
1243: return typePrecedence;
1244: }
1245:
1246: /**
1247: * Get the name of the corresponding Java type.
1248: *
1249: * Each SQL type has a corresponding Java type. When a SQL value is
1250: * passed to a Java method, it is translated to its corresponding Java
1251: * type. For example, when a SQL date column is passed to a method,
1252: * it is translated to a java.sql.Date.
1253: *
1254: * @return The name of the corresponding Java type.
1255: */
1256: public String getCorrespondingJavaTypeName() {
1257: if (SanityManager.DEBUG) {
1258: if (formatId == StoredFormatIds.REF_TYPE_ID) {
1259: SanityManager
1260: .THROWASSERT("getCorrespondingJavaTypeName not implemented for StoredFormatIds.REF_TYPE_ID");
1261: }
1262: SanityManager.ASSERT(javaTypeName != null,
1263: "javaTypeName expected to be non-null");
1264: }
1265: return javaTypeName;
1266: }
1267:
1268: /**
1269: * Get the name of the corresponding Java type.
1270: *
1271: * This method is used directly from EmbedResultSetMetaData (jdbc)
1272: * to return the corresponding type (as choosen by getObject).
1273: * It solves a specific problem for BLOB types where the
1274: * getCorrespondingJavaTypeName() is used internall for casting
1275: * which doesn't work if changed from byte[] to java.sql.Blob.
1276: * So we do it here instread, to avoid unexpected sideeffects.
1277: *
1278: * @return The name of the corresponding Java type.
1279: */
1280: public String getResultSetMetaDataTypeName() {
1281: if ((BLOB_ID != null) && BLOB_ID.equals(this ))
1282: return "java.sql.Blob";
1283: if ((CLOB_ID != null) && CLOB_ID.equals(this ))
1284: return "java.sql.Clob";
1285: if ((NCLOB_ID != null) && NCLOB_ID.equals(this ))
1286: return "java.sql.Clob";
1287: return getCorrespondingJavaTypeName();
1288: }
1289:
1290: /**
1291: * Get the maximum maximum width of the type (that's not a typo). For
1292: * types with variable length, this is the absolute maximum for the type.
1293: *
1294: * @return The maximum maximum width of the type
1295: */
1296: public int getMaximumMaximumWidth() {
1297: return maxMaxWidth;
1298: }
1299:
1300: /**
1301: * Converts this TypeId, given a data type descriptor (including length/precision),
1302: * to a string. E.g.
1303: *
1304: * VARCHAR(30)
1305: *
1306: *
1307: * For most data types, we just return the SQL type name.
1308: *
1309: * @param dts Data type descriptor that holds the length/precision etc. as necessary
1310: *
1311: * @return String version of datatype, suitable for running through
1312: * the Parser.
1313: */
1314: public String toParsableString(DataTypeDescriptor dts) {
1315: return baseTypeId.toParsableString(dts);
1316: }
1317:
1318: /**
1319: * Is this a type id for a numeric type?
1320: *
1321: * @return Whether or not this a type id for a numeric type.
1322: */
1323: public boolean isNumericTypeId() {
1324: return isNumericTypeId;
1325: }
1326:
1327: /**
1328: * Is this a type id for a decimal type?
1329: *
1330: * @return Whether or not this a type id for a decimal type.
1331: */
1332: public boolean isDecimalTypeId() {
1333: return isDecimalTypeId;
1334: }
1335:
1336: /**
1337: * Is this a type id for a boolean type?
1338: *
1339: * @return Whether or not this a type id for a boolean type.
1340: */
1341: public boolean isBooleanTypeId() {
1342: return isBooleanTypeId;
1343: }
1344:
1345: /**
1346: * Is this a type id for a ref type?
1347: *
1348: * @return Whether or not this a type id for a ref type.
1349: */
1350: public boolean isRefTypeId() {
1351: return isRefTypeId;
1352: }
1353:
1354: /**
1355: * Is this a type id for a concatable type?
1356: *
1357: * @return Whether or not this a type id for a concatable type.
1358: */
1359: public boolean isConcatableTypeId() {
1360: return isConcatableTypeId;
1361: }
1362:
1363: /**
1364: * Is this a type id for a bit type?
1365: *
1366: * @return Whether or not this a type id for a bit type.
1367: */
1368: public boolean isBitTypeId() {
1369: return isBitTypeId;
1370: }
1371:
1372: /**
1373: * Is this a type id for a LOB type?
1374: *
1375: * @return Whether or not this a type id for a LOB type.
1376: */
1377: public boolean isLOBTypeId() {
1378: return isLOBTypeId;
1379: }
1380:
1381: /**
1382: * Is this a type id for a long concatable type?
1383: *
1384: * @return Whether or not this a type id for a long concatable type.
1385: */
1386: public boolean isLongConcatableTypeId() {
1387: return isLongConcatableTypeId;
1388: }
1389:
1390: /**
1391: * Is this a type id for a user defined type?
1392: *
1393: * @return Whether or not this a type id for a user defined type.
1394: */
1395: public boolean isUserDefinedTypeId() {
1396: return isUserDefinedTypeId;
1397: }
1398:
1399: // Formatable interface
1400:
1401: /**
1402: * Read this object from a stream of stored objects.
1403: *
1404: * @param in read this.
1405: *
1406: * @exception IOException thrown on error
1407: * @exception ClassNotFoundException thrown on error
1408: */
1409: public void readExternal(ObjectInput in) throws IOException,
1410: ClassNotFoundException {
1411: baseTypeId = (BaseTypeIdImpl) in.readObject();
1412: /* We need to set the type specific variables
1413: * for user types when reading back off of the
1414: * disk becuse the baseTypeId was null when the
1415: * 0 argument constructor was called.
1416: */
1417: switch (formatId) {
1418: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
1419: setTypeIdSpecificInstanceVariables();
1420: }
1421: }
1422:
1423: /**
1424: * Write this object to a stream of stored objects.
1425: *
1426: * @param out write bytes here.
1427: *
1428: * @exception IOException thrown on error
1429: */
1430: public void writeExternal(ObjectOutput out) throws IOException {
1431: out.writeObject(baseTypeId);
1432: }
1433:
1434: /**
1435: * Get the formatID which corresponds to this class.
1436: *
1437: * @return the formatID of this class
1438: */
1439: public int getTypeFormatId() {
1440: return formatId;
1441: }
1442:
1443: /**
1444: * Get SQL null value.
1445: * @return SQL null value for this type.
1446: */
1447: public DataValueDescriptor getNull() {
1448: switch (formatId) {
1449: case StoredFormatIds.BIT_TYPE_ID:
1450: return new SQLBit();
1451:
1452: case StoredFormatIds.BOOLEAN_TYPE_ID:
1453: return new SQLBoolean();
1454:
1455: case StoredFormatIds.CHAR_TYPE_ID:
1456: return new SQLChar();
1457:
1458: // Implementation of DECIMAL can change.
1459: case StoredFormatIds.DECIMAL_TYPE_ID:
1460: return decimalImplementation.getNewNull();
1461:
1462: case StoredFormatIds.DOUBLE_TYPE_ID:
1463: return new SQLDouble();
1464:
1465: case StoredFormatIds.INT_TYPE_ID:
1466: return new SQLInteger();
1467:
1468: case StoredFormatIds.LONGINT_TYPE_ID:
1469: return new SQLLongint();
1470:
1471: case StoredFormatIds.LONGVARBIT_TYPE_ID:
1472: return new SQLLongVarbit();
1473:
1474: case StoredFormatIds.BLOB_TYPE_ID:
1475: return new SQLBlob();
1476:
1477: case StoredFormatIds.CLOB_TYPE_ID:
1478: return new SQLClob();
1479:
1480: case StoredFormatIds.NCLOB_TYPE_ID:
1481: return new SQLNClob();
1482:
1483: case StoredFormatIds.LONGVARCHAR_TYPE_ID:
1484: return new SQLLongvarchar();
1485:
1486: case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
1487: return new SQLNationalChar();
1488:
1489: case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
1490: return new SQLNationalVarchar();
1491:
1492: case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
1493: return new SQLNationalLongvarchar();
1494:
1495: case StoredFormatIds.REAL_TYPE_ID:
1496: return new SQLReal();
1497:
1498: case StoredFormatIds.REF_TYPE_ID:
1499: return new SQLRef();
1500:
1501: case StoredFormatIds.SMALLINT_TYPE_ID:
1502: return new SQLSmallint();
1503:
1504: case StoredFormatIds.TINYINT_TYPE_ID:
1505: return new SQLTinyint();
1506:
1507: case StoredFormatIds.DATE_TYPE_ID:
1508: return new SQLDate();
1509:
1510: case StoredFormatIds.TIME_TYPE_ID:
1511: return new SQLTime();
1512:
1513: case StoredFormatIds.TIMESTAMP_TYPE_ID:
1514: return new SQLTimestamp();
1515:
1516: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
1517: return new UserType();
1518:
1519: case StoredFormatIds.VARBIT_TYPE_ID:
1520: return new SQLVarbit();
1521:
1522: case StoredFormatIds.VARCHAR_TYPE_ID:
1523: return new SQLVarchar();
1524:
1525: case StoredFormatIds.XML_TYPE_ID:
1526: return new XML();
1527:
1528: default:
1529: if (SanityManager.DEBUG) {
1530: SanityManager
1531: .THROWASSERT("unexpected formatId in getNull() - "
1532: + formatId);
1533: }
1534: return null;
1535: }
1536: }
1537:
1538: /**
1539: * Is this type StreamStorable?
1540: *
1541: * @return true if this type has variable length.
1542: */
1543: public boolean streamStorable() {
1544: return isStringTypeId() || isBitTypeId();
1545: }
1546:
1547: //
1548: // Class methods
1549: //
1550:
1551: /**
1552: * Get the approximate length of this type in bytes.
1553: * For most datatypes this is just going to be
1554: * dts.getMaximumWidth(). Some types, such as
1555: * bit, will override this.
1556: *
1557: * @param dts Data type descriptor that holds the
1558: * length/precision etc. as necessary
1559: *
1560: * @return the length in bytes
1561: */
1562: public int getApproximateLengthInBytes(DataTypeDescriptor dts) {
1563: switch (formatId) {
1564: case StoredFormatIds.BIT_TYPE_ID:
1565: return (int) (Math.ceil(dts.getMaximumWidth() / 8d));
1566:
1567: case StoredFormatIds.CHAR_TYPE_ID:
1568: case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
1569: return (2 * dts.getMaximumWidth()) + 2;
1570:
1571: case StoredFormatIds.DECIMAL_TYPE_ID:
1572: // Return 200 if precision is max int
1573: if (dts.getPrecision() == Integer.MAX_VALUE) {
1574: return 200;
1575: } else {
1576: return 8 + (int) (Math.ceil(((double) dts
1577: .getPrecision()) / 2d));
1578: }
1579:
1580: case StoredFormatIds.LONGVARBIT_TYPE_ID:
1581: case StoredFormatIds.BLOB_TYPE_ID:
1582: case StoredFormatIds.CLOB_TYPE_ID:
1583: case StoredFormatIds.NCLOB_TYPE_ID:
1584: // RESOLVE: Should XML be here? What's this value mean, anyway?
1585: case StoredFormatIds.XML_TYPE_ID:
1586: return 10240;
1587:
1588: case StoredFormatIds.REF_TYPE_ID:
1589: return 16;
1590:
1591: case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
1592: /* For user types we'll guess on the high side
1593: ** (200) to avoid being too low in most cases.
1594: */
1595: return 200;
1596:
1597: case StoredFormatIds.VARBIT_TYPE_ID:
1598: // Return 200 if maximum width is max int
1599: if (dts.getMaximumWidth() == Integer.MAX_VALUE) {
1600: return 200;
1601: } else {
1602: return (int) (Math.ceil(dts.getMaximumWidth() / 8d));
1603: }
1604:
1605: case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
1606: case StoredFormatIds.VARCHAR_TYPE_ID:
1607: case StoredFormatIds.LONGVARCHAR_TYPE_ID:
1608: case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
1609: // Return 200 if maximum width is max int
1610: if (dts.getMaximumWidth() == Integer.MAX_VALUE) {
1611: return 200;
1612: } else {
1613: return (dts.getMaximumWidth() * 2) + 2;
1614: }
1615: /*
1616: ** For Date/time we know the exact size
1617: ** thanks to some investigative work by
1618: ** someone or other (sad isn't it).
1619: */
1620: case StoredFormatIds.DATE_TYPE_ID:
1621: return 18;
1622: case StoredFormatIds.TIME_TYPE_ID:
1623: return 16;
1624: case StoredFormatIds.TIMESTAMP_TYPE_ID:
1625: return 29;
1626:
1627: default:
1628: return dts.getMaximumWidth();
1629: }
1630: }
1631:
1632: /**
1633: * Get the base type id that is embedded in this type id. The base type
1634: * id is an object with a minimal implementation of TypeId that is intended
1635: * to be usable on the client side.
1636: */
1637: public BaseTypeIdImpl getBaseTypeId() {
1638: return baseTypeId;
1639: }
1640:
1641: /**
1642: * Get the precision of the merge of two Decimals
1643: *
1644: * @param leftType the left type
1645: * @param rightType the left type
1646: *
1647: * @return the resultant precision
1648: */
1649: public int getPrecision(DataTypeDescriptor leftType,
1650: DataTypeDescriptor rightType) {
1651: if (SanityManager.DEBUG) {
1652: if (formatId != StoredFormatIds.DECIMAL_TYPE_ID) {
1653: SanityManager
1654: .THROWASSERT("getPrecision() not expected to be called for formatId - "
1655: + formatId);
1656: }
1657: }
1658: long lscale = (long) leftType.getScale();
1659: long rscale = (long) rightType.getScale();
1660: long lprec = (long) leftType.getPrecision();
1661: long rprec = (long) rightType.getPrecision();
1662: long val;
1663:
1664: /*
1665: ** Take the maximum left of decimal digits plus the scale.
1666: */
1667: val = this .getScale(leftType, rightType)
1668: + Math.max(lprec - lscale, rprec - rscale);
1669:
1670: if (val > Integer.MAX_VALUE) {
1671: val = Integer.MAX_VALUE;
1672: }
1673: return (int) val;
1674: }
1675:
1676: /**
1677: * Get the scale of the merge of two decimals
1678: *
1679: * @param leftType the left type
1680: * @param rightType the left type
1681: *
1682: * @return the resultant precision
1683: */
1684: public int getScale(DataTypeDescriptor leftType,
1685: DataTypeDescriptor rightType) {
1686: if (SanityManager.DEBUG) {
1687: if (formatId != StoredFormatIds.DECIMAL_TYPE_ID) {
1688: SanityManager
1689: .THROWASSERT("getPrecision() not expected to be called for formatId - "
1690: + formatId);
1691: }
1692: }
1693: /*
1694: ** Retain greatest scale
1695: */
1696: return Math.max(leftType.getScale(), rightType.getScale());
1697: }
1698:
1699: /**
1700: * Does type hava a declared variable length (defined by the application).
1701: * Examples are CHAR(10), CLOB(1M).
1702: * Unbounded long types, like LONG VARCHAR return false here.
1703: * @return boolean true if type is variable length false if not.
1704: */
1705: public boolean variableLength() {
1706: switch (formatId) {
1707: case StoredFormatIds.BIT_TYPE_ID:
1708: case StoredFormatIds.VARBIT_TYPE_ID:
1709: case StoredFormatIds.DECIMAL_TYPE_ID:
1710: case StoredFormatIds.CHAR_TYPE_ID:
1711: case StoredFormatIds.VARCHAR_TYPE_ID:
1712: case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
1713: case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
1714: case StoredFormatIds.BLOB_TYPE_ID:
1715: case StoredFormatIds.CLOB_TYPE_ID:
1716: return true;
1717:
1718: default:
1719: return false;
1720: }
1721: }
1722: }
|