0001: /* Copyright (c) 2001-2005, The HSQL Development Group
0002: * All rights reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * Redistributions of source code must retain the above copyright notice, this
0008: * list of conditions and the following disclaimer.
0009: *
0010: * Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * Neither the name of the HSQL Development Group nor the names of its
0015: * contributors may be used to endorse or promote products derived from this
0016: * software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
0022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: */
0030:
0031: package org.hsqldb;
0032:
0033: import java.util.Locale;
0034:
0035: import org.hsqldb.resources.BundleHandler;
0036: import org.hsqldb.store.ValuePool;
0037:
0038: /**
0039: * Provides information intrinsic to each standard data type known to
0040: * HSQLDB. This includes all types for which standard type codes are known
0041: * at the time of writing and thus includes types that may not yet be
0042: * supported as table or procedure columns. <p>
0043: *
0044: * @author boucherb@users
0045: * @version 1.8.0
0046: * @since 1.7.2
0047: */
0048: final class DITypeInfo {
0049:
0050: // related to DatabaseMetaDataValues
0051: static final int columnNoNulls = 0;
0052: static final int columnNullable = 1;
0053: static final int typePredNone = 0;
0054: static final int typePredChar = 1;
0055: static final int typePredBasic = 2;
0056: static final int typeSearchable = 3;
0057:
0058: /** BundleHandler id for create params resource bundle. */
0059: private int hnd_create_params = -1;
0060:
0061: /** BundleHandler id for local names resource bundle. */
0062: private int hnd_local_names = -1;
0063:
0064: /** BundleHandler id for data type remarks resource bundle. */
0065: private int hnd_remarks = -1;
0066:
0067: /** The SQL type code on which this object is reporting. */
0068: private int type = Types.NULL;
0069:
0070: /** The HSQLDB subtype code on which this object is reporting. */
0071: private int typeSub = Types.TYPE_SUB_DEFAULT;
0072: boolean locale_set;
0073:
0074: /** Creates a new DITypeInfo object having the default Locale. */
0075: DITypeInfo() {
0076:
0077: // boucherb@users 20050515 - patch 1.8.0 - make setLocale lazy
0078: //setLocale(Locale.getDefault());
0079: }
0080:
0081: /**
0082: * Retrieves the maximum Integer.MAX_VALUE bounded length, in bytes, for
0083: * character types. <p>
0084: *
0085: * @return the maximum Integer.MAX_VALUE bounded length, in
0086: * bytes, for character types
0087: */
0088: Integer getCharOctLen() {
0089: return null;
0090: }
0091:
0092: /**
0093: * Retrieves the maximum Long.MAX_VALUE bounded length, in bytes, for
0094: * character types. <p>
0095: *
0096: * @return the maximum Long.MAX_VALUE bounded length, in
0097: * bytes, for character types
0098: */
0099: Long getCharOctLenAct() {
0100:
0101: switch (type) {
0102:
0103: case Types.CHAR:
0104: case Types.LONGVARCHAR:
0105: case Types.VARCHAR:
0106: return ValuePool.getLong(2L * Integer.MAX_VALUE);
0107:
0108: case Types.CLOB:
0109: return ValuePool.getLong(Long.MAX_VALUE);
0110:
0111: default:
0112: return null;
0113: }
0114: }
0115:
0116: /**
0117: * Retrieves the fully-qualified name of the Java class whose instances
0118: * are manufactured by HSQLDB to store table column values in
0119: * memory. <p>
0120: *
0121: * This is also typically the fully-qualified name of the Java class whose
0122: * instances are manufactured by HSQLDB in response to
0123: * jdbcResultSet.getObject(int). <p>
0124: *
0125: * @return the fully-qualified name of the Java class whose
0126: * instances are manufactured by HSQLDB to store
0127: * table column values in memory
0128: */
0129: String getColStClsName() {
0130: return Types.getColStClsName(type);
0131: }
0132:
0133: /**
0134: * Retrieves a character sequence representing a CSV list, in
0135: * DDL declaraion order, of the create parameters for the type. <p>
0136: *
0137: * @return a character sequence representing a CSV
0138: * list, in DDL declaraion order, of the create
0139: * parameters for the type.
0140: */
0141: String getCreateParams() {
0142:
0143: if (!locale_set) {
0144: setLocale(Locale.getDefault());
0145: }
0146:
0147: String names;
0148:
0149: switch (type) {
0150:
0151: case Types.CHAR:
0152: case Types.VARCHAR:
0153: names = "LENGTH";
0154: break;
0155:
0156: case Types.DECIMAL:
0157: case Types.NUMERIC:
0158: names = "PRECISION,SCALE";
0159: break;
0160:
0161: case Types.FLOAT:
0162: case Types.TIMESTAMP:
0163: names = "PRECISION";
0164: break;
0165:
0166: default:
0167: names = null;
0168: break;
0169: }
0170:
0171: return names;
0172: }
0173:
0174: /**
0175: * Retrieves the fully-qualified name of the HSQLDB-provided java.sql
0176: * interface implementation class whose instances would be manufactured
0177: * by HSQLDB to retrieve column values of this type, if the
0178: * the type does not have a standard Java mapping. <p>
0179: *
0180: * This value is simply the expected class name, regardless of whether
0181: * HSQLDB, the specific HSQLDB distribution instance or the hosting JVM
0182: * actually provide or support such implementations. That is, as of a
0183: * specific release, HSQLDB may not yet provide such an implementation
0184: * or may not automatically map to it or may not support it as a table
0185: * column type, the version of java.sql may not define the interface to
0186: * implement and the HSQLDB jar may not contain the implementation
0187: * classes, even if they are defined in the corresponding release
0188: * and build options and are supported under the hosting JVM's java.sql
0189: * version.<p>
0190: *
0191: * @return the fully-qualified name of the HSQLDB-provided java.sql
0192: * interface implementation class whose instances would
0193: * be manufactured by HSQLDB to retrieve column values of
0194: * this type, given that the type does not have a standard Java
0195: * mapping and regardless of whether a class with the indicated
0196: * name is actually implemented or available on the class path
0197: */
0198: String getCstMapClsName() {
0199:
0200: switch (type) {
0201:
0202: case Types.ARRAY:
0203: return "org.hsqldb.jdbc.jdbcArray";
0204:
0205: case Types.BLOB:
0206: return "org.hsqldb.jdbc.jdbcBlob";
0207:
0208: case Types.CLOB:
0209: return "org.hsqldb.jdbc.jdbcClob";
0210:
0211: case Types.DISTINCT:
0212: return "org.hsqldb.jdbc.jdbcDistinct";
0213:
0214: case Types.REF:
0215: return "org.hsqldb.jdbc.jdbcRef";
0216:
0217: case Types.STRUCT:
0218: return "org.hsqldb.jdbc.jdbcStruct";
0219:
0220: default:
0221: return null;
0222: }
0223: }
0224:
0225: // NOTES:
0226: // From recent usability testing, this patch and the corresponding patch in
0227: // jdbcResultSetMetaData together provide better compatibility with existing
0228: // tools than through the previous method of dynamically scanning each result
0229: // in jdbcResultSetMetaData. This is especially true given that many tools use
0230: // the display size to set their internal max # of characters reserved for
0231: // result columns at said position. Also, since adding implementation of
0232: // ResultSetMetaData retreived from PreparedStatement's getMetaData method,
0233: // there exists the case where there is no data to scan in order to determine
0234: // an approximation. Finally, since for plain old Statement objects the only
0235: // way to get metadata is to execute the query and since the scan approximation
0236: // can vary from one execution to the next, it turns out it's much "safer" and
0237: // more usable in a tool setting to simply indicate a large but expected
0238: // acceptable number of characters, rather than report either a number generally
0239: // too large to handle or a number too small to hold the actual expected maximum
0240: // number of characters for result colums of CHAR or VARCHAR types
0241:
0242: /**
0243: * Retrieves the maximum length that a String representation of
0244: * the type may have. <p>
0245: *
0246: * The calculation follows these rules: <p>
0247: *
0248: * <ol>
0249: * <li>Long character and datetime types:<p>
0250: *
0251: * The maximum length/precision, repectively.<p>
0252: *
0253: * <li>CHAR and VARCHAR types: <p>
0254: *
0255: * The value of the system property hsqldb.max_xxxchar_display_size
0256: * or the magic value 32766 (0x7FFE) (tested usable/accepted by most
0257: * tools and compatible with assumptions made by java.io read/write
0258: * UTF) when the system property is not defined or is not accessible,
0259: * due to security constraints. <p>
0260: *
0261: * <li>Number types: <p>
0262: *
0263: * The max precision, plus the length of the negation character (1),
0264: * plus (if applicable) the maximum number of characters that may
0265: * occupy the exponent character sequence. <p>
0266: *
0267: * <li>BOOLEAN/BIT types: <p>
0268: *
0269: * The length of the character sequence "false" (5), the longer of the
0270: * two boolean value String representations. <p>
0271: *
0272: * <li>All remaining types: <p>
0273: *
0274: * The result of whatever calculation must be performed to determine
0275: * the maximum length of the type's String representation. If the
0276: * maximum display size is unknown, unknowable or inapplicable, then
0277: * zero is returned. <p>
0278: *
0279: * </ol>
0280: *
0281: * @return the maximum length that a String representation of
0282: * the type may have, or zero (0) if unknown or unknowable
0283: */
0284: int getMaxDisplaySize() {
0285: return Types.getMaxDisplaySize(type);
0286: }
0287:
0288: /**
0289: * Retrieves the data type, as an Integer. <p>
0290: *
0291: * @return the data type, as an Integer.
0292: */
0293: Integer getDataType() {
0294: return ValuePool.getInt(type);
0295: }
0296:
0297: /**
0298: * Retrieves the data subtype, as an Integer. <p>
0299: *
0300: * @return the data subtype, as an Integer
0301: */
0302: Integer getDataTypeSub() {
0303: return ValuePool.getInt(typeSub);
0304: }
0305:
0306: /**
0307: * Retrieves the implied or single permitted scale for exact numeric
0308: * types, when no scale is declared or no scale declaration is
0309: * permitted. <p>
0310: *
0311: * @return the implied or single permitted scale for exact numeric
0312: * types, when no scale is declared or no scale declaration
0313: * is permitted
0314: */
0315: Integer getDefaultScale() {
0316:
0317: switch (type) {
0318:
0319: case Types.BIGINT:
0320: case Types.INTEGER:
0321: case Types.SMALLINT:
0322: case Types.TINYINT:
0323: return ValuePool.getInt(0);
0324:
0325: default:
0326: return null;
0327: }
0328: }
0329:
0330: /**
0331: * Retrieves null (not implemented). <p>
0332: *
0333: * @return null (not implemented)
0334: */
0335: Integer getIntervalPrecision() {
0336: return null;
0337: }
0338:
0339: /**
0340: * Retrieves the character(s) prefixing a literal of this type. <p>
0341: *
0342: * @return the character(s) prefixing a literal of this type.
0343: */
0344: String getLiteralPrefix() {
0345:
0346: switch (type) {
0347:
0348: case Types.BINARY:
0349: case Types.BLOB:
0350: case Types.CHAR:
0351: case Types.CLOB:
0352: case Types.LONGVARBINARY:
0353: case Types.LONGVARCHAR:
0354: case Types.VARBINARY:
0355: case Types.VARCHAR:
0356: return "'";
0357:
0358: case Types.DATALINK:
0359: return "'"; // hypothetically: "{url '";
0360:
0361: case Types.DATE:
0362: return "'"; // or JDBC escape: "{d '";
0363:
0364: case Types.OTHER:
0365: return "'"; // hypothetically: "{o '"; or new "pkg.cls"(...)
0366:
0367: case Types.TIME:
0368: return "'"; // or JDBC escape: "{t '";
0369:
0370: case Types.TIMESTAMP:
0371: return "'"; // or JDBC escape: "{ts '";
0372:
0373: case Types.XML:
0374: return "'"; // hypothetically: "{xml '";
0375:
0376: default:
0377: return null;
0378: }
0379: }
0380:
0381: /**
0382: * Retrieves the character(s) terminating a literal of this type. <p>
0383: *
0384: * @return the character(s) terminating a literal of this type
0385: */
0386: String getLiteralSuffix() {
0387:
0388: switch (type) {
0389:
0390: case Types.BINARY:
0391: case Types.BLOB:
0392: case Types.CHAR:
0393: case Types.CLOB:
0394: case Types.LONGVARBINARY:
0395: case Types.LONGVARCHAR:
0396: case Types.VARBINARY:
0397: case Types.VARCHAR:
0398: return "'";
0399:
0400: case Types.DATALINK:
0401: case Types.DATE:
0402: case Types.OTHER:
0403: case Types.TIME:
0404: case Types.TIMESTAMP:
0405: case Types.XML:
0406: return "'"; // or JDBC close escape: "'}";
0407:
0408: default:
0409: return null;
0410: }
0411: }
0412:
0413: /**
0414: * Retrieves a localized representation of the type's name, for human
0415: * consumption only. <p>
0416: *
0417: * @return a localized representation of the type's name
0418: */
0419: String getLocalName() {
0420:
0421: if (!locale_set) {
0422: setLocale(Locale.getDefault());
0423: }
0424:
0425: String key = this .getTypeName();
0426:
0427: return BundleHandler.getString(hnd_local_names, key);
0428: }
0429:
0430: /**
0431: * Retrieves the maximum Short.MAX_VALUE bounded scale supported
0432: * for the type. <p>
0433: *
0434: * @return the maximum Short.MAX_VALUE bounded scale supported
0435: * for the type
0436: */
0437: Integer getMaxScale() {
0438:
0439: switch (type) {
0440:
0441: case Types.BIGINT:
0442: case Types.DATE:
0443: case Types.TIME:
0444: case Types.INTEGER:
0445: case Types.SMALLINT:
0446: case Types.TINYINT:
0447: return ValuePool.getInt(0);
0448:
0449: case Types.TIMESTAMP:
0450: return ValuePool.getInt(6);
0451:
0452: case Types.DECIMAL:
0453: case Types.NUMERIC:
0454: return ValuePool.getInt(Short.MAX_VALUE);
0455:
0456: case Types.FLOAT:
0457: case Types.REAL:
0458: case Types.DOUBLE:
0459: return ValuePool.getInt(306);
0460:
0461: default:
0462: return null;
0463: }
0464: }
0465:
0466: /**
0467: * Retrieves the maximum Integer.MAX_VALUE bounded scale supported for
0468: * the type. <p>
0469: *
0470: * @return the maximum Integer.MAX_VALUE bounded scale supported
0471: * for the type
0472: */
0473: Integer getMaxScaleAct() {
0474:
0475: switch (type) {
0476:
0477: case Types.DECIMAL:
0478: case Types.NUMERIC:
0479: return ValuePool.getInt(Integer.MAX_VALUE);
0480:
0481: default:
0482: return getMaxScale();
0483: }
0484: }
0485:
0486: /**
0487: * Retrieves the minumum Short.MIN_VALUE bounded scale supported for
0488: * the type. <p>
0489: *
0490: * @return the minumum Short.MIN_VALUE bounded scale
0491: * supported for the type
0492: */
0493: Integer getMinScale() {
0494:
0495: switch (type) {
0496:
0497: case Types.BIGINT:
0498: case Types.DATE:
0499: case Types.INTEGER:
0500: case Types.SMALLINT:
0501: case Types.TIME:
0502: case Types.TIMESTAMP:
0503: case Types.TINYINT:
0504: case Types.DECIMAL:
0505: case Types.NUMERIC:
0506: return ValuePool.getInt(0);
0507:
0508: case Types.FLOAT:
0509: case Types.REAL:
0510: case Types.DOUBLE:
0511: return ValuePool.getInt(-324);
0512:
0513: default:
0514: return null;
0515: }
0516: }
0517:
0518: /**
0519: * Retrieves the minumum Integer.MIN_VALUE bounded scale supported
0520: * for the type. <p>
0521: *
0522: * @return the minumum Integer.MIN_VALUE bounded scale supported
0523: * for the type
0524: */
0525: Integer getMinScaleAct() {
0526: return getMinScale();
0527: }
0528:
0529: /**
0530: * Retrieves the DatabaseMetaData default nullability code for
0531: * the type. <p>
0532: *
0533: * @return the DatabaseMetaData nullability code for the type.
0534: */
0535: Integer getNullability() {
0536: return ValuePool.getInt(columnNullable);
0537: }
0538:
0539: /**
0540: * Retrieves the number base which is to be used to interpret the value
0541: * reported by getPrecision(). <p>
0542: *
0543: * @return the number base which is to be used to interpret the
0544: * value reported by getPrecision()
0545: */
0546: Integer getNumPrecRadix() {
0547:
0548: switch (type) {
0549:
0550: case Types.BIGINT:
0551: case Types.DECIMAL:
0552: case Types.DOUBLE:
0553: case Types.INTEGER:
0554: case Types.NUMERIC:
0555: case Types.REAL:
0556: case Types.SMALLINT:
0557: case Types.TINYINT:
0558: return ValuePool.getInt(10);
0559:
0560: case Types.FLOAT:
0561: return ValuePool.getInt(2);
0562:
0563: default:
0564: return null;
0565: }
0566: }
0567:
0568: /**
0569: * Retrieves the maximum Integer.MAX_VALUE bounded length or precision for
0570: * the type. <p>
0571: *
0572: * @return the maximum Integer.MAX_VALUE bounded length or
0573: * precision for the type
0574: */
0575: Integer getPrecision() {
0576:
0577: int p = Types.getPrecision(type);
0578:
0579: return p == 0 ? null : ValuePool.getInt(p);
0580: }
0581:
0582: /**
0583: * Retrieves the maximum Long.MAX_VALUE bounded length or precision for
0584: * the type. <p>
0585: *
0586: * @return the maximum Long.MAX_VALUE bounded length or
0587: * precision for the type
0588: */
0589: Long getPrecisionAct() {
0590:
0591: Integer temp = getPrecision();
0592:
0593: if (temp == null) {
0594: return ValuePool.getLong(Long.MAX_VALUE);
0595: } else {
0596: return ValuePool.getLong(temp.longValue());
0597: }
0598: }
0599:
0600: /**
0601: * Retrieves the localized remarks (if any) on the type. <p>
0602: *
0603: * @return the localized remarks on the type.
0604: */
0605: String getRemarks() {
0606:
0607: if (!locale_set) {
0608: setLocale(Locale.getDefault());
0609: }
0610:
0611: String key = this .getTypeName();
0612:
0613: return BundleHandler.getString(hnd_remarks, key);
0614: }
0615:
0616: /**
0617: * Retrieves the DatabaseMetaData searchability code for the type. <p>
0618: *
0619: * @return the DatabaseMetaData searchability code for the type
0620: */
0621: Integer getSearchability() {
0622: return Types.isSearchable(type) ? ValuePool
0623: .getInt(typeSearchable) : ValuePool
0624: .getInt(typePredNone);
0625: }
0626:
0627: /**
0628: * Retrieves the SQL CLI data type code for the type. <p>
0629: *
0630: * @return the SQL CLI data type code for the type
0631: */
0632: Integer getSqlDataType() {
0633:
0634: // values from SQL200n SQL CLI spec, or DITypes (which in turn borrows
0635: // first from java.sql.Types and then SQL200n SQL CLI spec) if there
0636: // was no corresponding value in SQL CLI
0637: switch (type) {
0638:
0639: case Types.ARRAY:
0640: return ValuePool.getInt(Types.SQL_ARRAY); // SQL_ARRAY
0641:
0642: case Types.BIGINT:
0643: return ValuePool.getInt(Types.SQL_BIGINT); // SQL_BIGINT
0644:
0645: case Types.BINARY:
0646: return ValuePool.getInt(Types.SQL_BLOB); // fredt- was SQL_BIT_VARYING
0647:
0648: case Types.BOOLEAN:
0649: return ValuePool.getInt(Types.SQL_BOOLEAN); // SQL_BOOLEAN
0650:
0651: case Types.BLOB:
0652: return ValuePool.getInt(Types.SQL_BLOB); // SQL_BLOB
0653:
0654: case Types.CHAR:
0655: return ValuePool.getInt(Types.SQL_CHAR); // SQL_CHAR
0656:
0657: case Types.CLOB:
0658: return ValuePool.getInt(Types.SQL_CLOB); // SQL_CLOB
0659:
0660: case Types.DATALINK:
0661: return ValuePool.getInt(Types.SQL_DATALINK); // SQL_DATALINK
0662:
0663: case Types.DATE:
0664:
0665: // NO: This is the _concise_ code, whereas what we want to
0666: // return here is the Data Type Code column value from
0667: // Table 38 in the SQL 200n FCD. This method is used
0668: // by DatabaseInformationMain to list the sql type
0669: // column in the SYSTEM_TYPEINFO table, which is specified
0670: // by JDBC as the sql data type code, not the concise code.
0671: // That is why there is a sql datetime sub column
0672: // specified as well.
0673: // return ValuePool.getInt(Types.SQL_DATE); // fredt - was SQL_DATETIME
0674: return ValuePool.getInt(Types.SQL_DATETIME);
0675:
0676: case Types.DECIMAL:
0677: return ValuePool.getInt(Types.SQL_DECIMAL); // SQL_DECIMAL
0678:
0679: case Types.DISTINCT:
0680: return ValuePool.getInt(Types.SQL_UDT); // SQL_UDT
0681:
0682: case Types.DOUBLE:
0683: return ValuePool.getInt(Types.SQL_DOUBLE); // SQL_DOUBLE
0684:
0685: case Types.FLOAT:
0686: return ValuePool.getInt(Types.SQL_FLOAT); // SQL_FLOAT
0687:
0688: case Types.INTEGER:
0689: return ValuePool.getInt(Types.SQL_INTEGER); // SQL_INTEGER
0690:
0691: case Types.JAVA_OBJECT:
0692: return ValuePool.getInt(Types.JAVA_OBJECT); // N/A - maybe SQL_UDT?
0693:
0694: case Types.LONGVARBINARY:
0695: return ValuePool.getInt(Types.SQL_BLOB); // was SQL_BIT_VARYING
0696:
0697: case Types.LONGVARCHAR:
0698: return ValuePool.getInt(Types.SQL_CLOB); //
0699:
0700: case Types.NULL:
0701: return ValuePool.getInt(Types.SQL_ALL_TYPES); // SQL_ALL_TYPES
0702:
0703: case Types.NUMERIC:
0704: return ValuePool.getInt(Types.SQL_NUMERIC); // SQL_NUMERIC
0705:
0706: case Types.OTHER:
0707: return ValuePool.getInt(Types.OTHER); // N/A - maybe SQL_UDT?
0708:
0709: case Types.REAL:
0710: return ValuePool.getInt(Types.SQL_REAL); // SQL_REAL
0711:
0712: case Types.REF:
0713: return ValuePool.getInt(Types.SQL_REF); // SQL_REF
0714:
0715: case Types.SMALLINT:
0716: return ValuePool.getInt(Types.SQL_SMALLINT); // SQL_SMALLINTEGER
0717:
0718: case Types.STRUCT:
0719: return ValuePool.getInt(Types.SQL_UDT); // SQL_UDT
0720:
0721: case Types.TIME:
0722:
0723: // NO: This is the _concise_ code, whereas what we want to
0724: // return here is the Data Type Code column value from
0725: // Table 38 in the SQL 200n FCD. This method is used
0726: // by DatabaseInformationMain to list the sql type
0727: // column in the SYSTEM_TYPEINFO table, which is specified
0728: // by JDBC as the sql data type code, not the concise code.
0729: // That is why there is a sql datetime sub column
0730: // specified as well.
0731: // return ValuePool.getInt(Types.SQL_TIME); // fredt - was SQL_DATETIME
0732: return ValuePool.getInt(Types.SQL_DATETIME);
0733:
0734: case Types.TIMESTAMP:
0735:
0736: // NO: This is the _concise_ code, whereas what we want to
0737: // return here is the Data Type Code column value from
0738: // Table 38 in the SQL CLI 200n FCD. This method is used
0739: // by DatabaseInformationMain to list the sql type
0740: // column in the SYSTEM_TYPEINFO table, which is specified
0741: // by JDBC as the sql data type code, not the concise code.
0742: // That is why there is a sql datetime sub column
0743: // specified as well.
0744: // return ValuePool.getInt(Types.SQL_TIMESTAMP); // fredt - was SQL_DATETIME
0745: return ValuePool.getInt(Types.SQL_DATETIME);
0746:
0747: case Types.TINYINT:
0748: return ValuePool.getInt(Types.TINYINT); // N/A
0749:
0750: case Types.VARBINARY:
0751: return ValuePool.getInt(Types.SQL_BLOB); // SQL_BIT_VARYING
0752:
0753: case Types.VARCHAR:
0754: return ValuePool.getInt(Types.SQL_VARCHAR); // SQL_VARCHAR
0755:
0756: case Types.XML:
0757: return ValuePool.getInt(Types.SQL_XML); // SQL_XML
0758:
0759: default:
0760: return null;
0761: }
0762: }
0763:
0764: /**
0765: * Retrieves the SQL CLI datetime subcode for the type. <p>
0766: *
0767: * @return the SQL CLI datetime subcode for the type
0768: */
0769: Integer getSqlDateTimeSub() {
0770:
0771: switch (type) {
0772:
0773: case Types.DATE:
0774: return ValuePool.getInt(1);
0775:
0776: case Types.TIME:
0777: return ValuePool.getInt(2);
0778:
0779: case Types.TIMESTAMP:
0780: return ValuePool.getInt(3);
0781:
0782: default:
0783: return null;
0784: }
0785: }
0786:
0787: /**
0788: * Retrieve the fully qualified name of the recommended standard Java
0789: * primitive, class or java.sql interface mapping for the type. <p>
0790: *
0791: * @return the fully qualified name of the recommended standard Java
0792: * primitive, class or java.sql interface mapping for
0793: * the type
0794: */
0795: String getStdMapClsName() {
0796:
0797: switch (type) {
0798:
0799: case Types.ARRAY:
0800: return "java.sql.Array";
0801:
0802: case Types.BIGINT:
0803: return "long";
0804:
0805: case Types.BINARY:
0806: case Types.LONGVARBINARY:
0807: case Types.VARBINARY:
0808: return "[B";
0809:
0810: case Types.BOOLEAN:
0811: return "boolean";
0812:
0813: case Types.BLOB:
0814: return "java.sql.Blob";
0815:
0816: case Types.CHAR:
0817: case Types.LONGVARCHAR:
0818: case Types.VARCHAR:
0819: return "java.lang.String";
0820:
0821: case Types.CLOB:
0822: return "java.sql.Clob";
0823:
0824: case Types.DATALINK:
0825: return "java.net.URL";
0826:
0827: case Types.DATE:
0828: return "java.sql.Date";
0829:
0830: case Types.DECIMAL:
0831: case Types.NUMERIC:
0832: return "java.math.BigDecimal";
0833:
0834: case Types.DISTINCT:
0835: case Types.JAVA_OBJECT:
0836: case Types.OTHER:
0837: case Types.XML: // ???
0838: return "java.lang.Object";
0839:
0840: case Types.REAL:
0841: return "float";
0842:
0843: case Types.FLOAT:
0844: case Types.DOUBLE:
0845: return "double";
0846:
0847: case Types.INTEGER:
0848: return "int";
0849:
0850: case Types.NULL:
0851: return "null";
0852:
0853: case Types.REF:
0854: return "java.sql.Ref";
0855:
0856: case Types.SMALLINT:
0857: return "short";
0858:
0859: case Types.STRUCT:
0860: return "java.sql.Struct";
0861:
0862: case Types.TIME:
0863: return "java.sql.Time";
0864:
0865: case Types.TIMESTAMP:
0866: return "java.sql.Timestamp";
0867:
0868: case Types.TINYINT:
0869: return "byte";
0870:
0871: default:
0872: return null;
0873: }
0874: }
0875:
0876: /**
0877: * Retrieves the data type as an int. <p>
0878: *
0879: * @return the data type as an int
0880: */
0881: int getTypeCode() {
0882: return type;
0883: }
0884:
0885: /**
0886: * Retrieves the canonical data type name HSQLDB associates with
0887: * the type. <p>
0888: *
0889: * This typically matches the designated JDBC name, with one or
0890: * two exceptions. <p>
0891: *
0892: * @return the canonical data type name HSQLDB associates with the type
0893: */
0894: String getTypeName() {
0895:
0896: return typeSub == Types.TYPE_SUB_IGNORECASE ? Types
0897: .getTypeName(Types.VARCHAR_IGNORECASE) : Types
0898: .getTypeName(type);
0899: }
0900:
0901: /**
0902: * Retrieves the HSQLDB data subtype as an int. <p>
0903: *
0904: * @return the HSQLDB data subtype as an int
0905: */
0906: int getTypeSub() {
0907: return this .typeSub;
0908: }
0909:
0910: /**
0911: * Retrieves whether the type can be an IDENTITY type. <p>
0912: *
0913: * @return whether the type can be an IDENTITY type.
0914: */
0915: Boolean isAutoIncrement() {
0916:
0917: switch (type) {
0918:
0919: case Types.DECIMAL:
0920: case Types.DOUBLE:
0921: case Types.FLOAT:
0922: case Types.NUMERIC:
0923: case Types.REAL:
0924: case Types.SMALLINT:
0925: case Types.TINYINT:
0926: return Boolean.FALSE;
0927:
0928: case Types.BIGINT:
0929: case Types.INTEGER:
0930: return Boolean.TRUE;
0931:
0932: default:
0933: return null;
0934: }
0935: }
0936:
0937: /**
0938: * Retrieves whether the type is case-sensitive in collations and
0939: * comparisons. <p>
0940: *
0941: * @return whether the type is case-sensitive in collations and
0942: * comparisons.
0943: */
0944: Boolean isCaseSensitive() {
0945:
0946: return typeSub == Types.TYPE_SUB_IGNORECASE ? Boolean.FALSE
0947: : Types.isCaseSensitive(type);
0948: }
0949:
0950: /**
0951: * Retrieves whether, under the current release, class path and hosting
0952: * JVM, HSQLDB supports storing this type in table columns. <p>
0953: *
0954: * This value also typically represents whether HSQLDB supports retrieving
0955: * values of this type in the columns of ResultSets.
0956: * @return whether, under the current release, class path
0957: * and hosting JVM, HSQLDB supports storing this
0958: * type in table columns
0959: */
0960: Boolean isColStClsSupported() {
0961:
0962: return ValuePool.getBoolean(type == Types.NULL ? true
0963: : getColStClsName() != null);
0964: }
0965:
0966: /**
0967: * Retrieves whether values of this type have a fixed precision and
0968: * scale. <p>
0969: *
0970: * @return whether values of this type have a fixed
0971: * precision and scale.
0972: */
0973: Boolean isFixedPrecisionScale() {
0974:
0975: switch (type) {
0976:
0977: case Types.BIGINT:
0978: case Types.DECIMAL:
0979: case Types.DOUBLE:
0980: case Types.FLOAT:
0981: case Types.INTEGER:
0982: case Types.NUMERIC:
0983: case Types.REAL:
0984: case Types.SMALLINT:
0985: case Types.TINYINT:
0986: return Boolean.FALSE;
0987:
0988: default:
0989: return null;
0990: }
0991: }
0992:
0993: /**
0994: * Retrieve whether the fully qualified name reported by getStdMapClsName()
0995: * is supported as a jdbcResultSet.getXXX return type under the current
0996: * HSQLDB release, class path and hosting JVM. <p>
0997: *
0998: * @return whether the fully qualified name reported by getStdMapClsName()
0999: * is supported as a jdbcResultSet.getXXX return type under the current
1000: * HSQLDB release, class path and hosting JVM.
1001: */
1002: Boolean isStdMapClsSupported() {
1003:
1004: // its ok to use Class.forName here instead of nameSpace.classForName,
1005: // because all standard map classes are loaded by the boot loader
1006: boolean isSup = false;
1007:
1008: switch (type) {
1009:
1010: case Types.ARRAY: {
1011: try {
1012: Class.forName("java.sql.Array");
1013:
1014: isSup = true;
1015: } catch (Exception e) {
1016: isSup = false;
1017: }
1018:
1019: break;
1020: }
1021: case Types.BLOB: {
1022: try {
1023: Class.forName("java.sql.Blob");
1024:
1025: isSup = true;
1026: } catch (Exception e) {
1027: isSup = false;
1028: }
1029:
1030: break;
1031: }
1032: case Types.CLOB: {
1033: try {
1034: Class.forName("java.sql.Clob");
1035:
1036: isSup = true;
1037: } catch (Exception e) {
1038: isSup = false;
1039: }
1040:
1041: break;
1042: }
1043: case Types.DISTINCT: {
1044: isSup = false;
1045:
1046: break;
1047: }
1048: case Types.REF: {
1049: try {
1050: Class.forName("java.sql.Ref");
1051:
1052: isSup = true;
1053: } catch (Exception e) {
1054: isSup = false;
1055: }
1056:
1057: break;
1058: }
1059: case Types.STRUCT: {
1060: try {
1061: Class.forName("java.sql.Struct");
1062:
1063: isSup = true;
1064: } catch (Exception e) {
1065: isSup = false;
1066: }
1067:
1068: break;
1069: }
1070: default: {
1071: isSup = (getStdMapClsName() != null);
1072:
1073: break;
1074: }
1075: }
1076:
1077: return ValuePool.getBoolean(isSup);
1078: }
1079:
1080: /**
1081: * Retrieves whether, under the current release, class path and
1082: * hosting JVM, HSQLDB supports passing or receiving this type as
1083: * the value of a procedure column. <p>
1084: *
1085: * @return whether, under the current release, class path and
1086: * hosting JVM, HSQLDB supports passing or receiving
1087: * this type as the value of a procedure column.
1088: */
1089: Boolean isSupportedAsPCol() {
1090:
1091: switch (type) {
1092:
1093: case Types.NULL: // - for void return type
1094: case Types.JAVA_OBJECT: // - for Connection as first parm and
1095:
1096: // Object for return type
1097: case Types.ARRAY: // - for Object[] row of Trigger.fire()
1098: return Boolean.TRUE;
1099:
1100: default:
1101: return isSupportedAsTCol();
1102: }
1103: }
1104:
1105: /**
1106: * Retrieves whether, under the current release, class path and
1107: * hosting JVM, HSQLDB supports this as the type of a table
1108: * column. <p>
1109: *
1110: * @return whether, under the current release, class path
1111: * and hosting JVM, HSQLDB supports this type
1112: * as the values of a table column
1113: */
1114: Boolean isSupportedAsTCol() {
1115:
1116: String columnTypeName;
1117:
1118: if (type == Types.NULL) {
1119: return Boolean.FALSE;
1120: }
1121:
1122: columnTypeName = Types.getTypeString(type);
1123:
1124: return ValuePool.getBoolean(columnTypeName != null);
1125: }
1126:
1127: /**
1128: * Retrieves whether values of this type are unsigned. <p>
1129: *
1130: * @return whether values of this type are unsigned
1131: */
1132: Boolean isUnsignedAttribute() {
1133: return Types.isUnsignedAttribute(type);
1134: }
1135:
1136: /**
1137: * Assigns the Locale object used to retrieve this object's
1138: * resource bundle dependent values. <p>
1139: *
1140: * @param l the Locale object used to retrieve this object's resource
1141: * bundle dependent values
1142: */
1143: void setLocale(Locale l) {
1144:
1145: if (l == null) {
1146: hnd_create_params = hnd_local_names = hnd_remarks = -1;
1147: locale_set = false;
1148:
1149: return;
1150: }
1151:
1152: Locale oldLocale;
1153:
1154: synchronized (BundleHandler.class) {
1155: oldLocale = BundleHandler.getLocale();
1156:
1157: BundleHandler.setLocale(l);
1158:
1159: hnd_create_params = BundleHandler.getBundleHandle(
1160: "data-type-create-parameters", null);
1161: hnd_local_names = BundleHandler.getBundleHandle(
1162: "data-type-names", null);
1163: hnd_remarks = BundleHandler.getBundleHandle(
1164: "data-type-remarks", null);
1165:
1166: BundleHandler.setLocale(oldLocale);
1167:
1168: locale_set = true;
1169: }
1170: }
1171:
1172: /**
1173: * Assigns the SQL data type code on which this object is to report. <p>
1174: *
1175: * @param type the SQL data type code on which this object is to report
1176: */
1177: void setTypeCode(int type) {
1178: this .type = type;
1179: }
1180:
1181: /**
1182: * Assigns the HSQLDB data subtype code on which this object is
1183: * to report. <p>
1184: *
1185: * @param typeSub the HSQLDB data subtype code on which this object
1186: * is to report
1187: */
1188: void setTypeSub(int typeSub) {
1189: this.typeSub = typeSub;
1190: }
1191: }
|