EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [JdbcDatabaseMetaData.java]

nameclass, %method, %block, %line, %
JdbcDatabaseMetaData.java100% (1/1)97%  (178/184)93%  (2181/2348)91%  (551.9/609)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcDatabaseMetaData100% (1/1)97%  (178/184)93%  (2181/2348)91%  (551.9/609)
getFunctionColumns (String, String, String, String): ResultSet 0%   (0/1)0%   (0/4)0%   (0/1)
getFunctions (String, String, String): ResultSet 0%   (0/1)0%   (0/4)0%   (0/1)
getPseudoColumns (String, String, String, String): ResultSet 0%   (0/1)0%   (0/2)0%   (0/1)
isWrapperFor (Class): boolean 0%   (0/1)0%   (0/11)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/13)0%   (0/1)
unwrap (Class): Object 0%   (0/1)0%   (0/10)0%   (0/3)
getURL (): String 100% (1/1)58%  (7/12)50%  (2/4)
getUserName (): String 100% (1/1)58%  (7/12)50%  (2/4)
isReadOnly (): boolean 100% (1/1)58%  (7/12)50%  (2/4)
getCatalogs (): ResultSet 100% (1/1)72%  (13/18)67%  (4/6)
getSchemas (): ResultSet 100% (1/1)72%  (13/18)67%  (4/6)
getTableTypes (): ResultSet 100% (1/1)72%  (13/18)67%  (4/6)
getTypeInfo (): ResultSet 100% (1/1)75%  (15/20)71%  (5/7)
supportsMixedCaseQuotedIdentifiers (): boolean 100% (1/1)86%  (12/14)80%  (4/5)
getSchemas (String, String): ResultSet 100% (1/1)86%  (31/36)80%  (8/10)
getSuperTables (String, String, String): ResultSet 100% (1/1)88%  (36/41)71%  (5/7)
getVersionColumns (String, String, String): ResultSet 100% (1/1)88%  (36/41)71%  (5/7)
nullsAreSortedLow (): boolean 100% (1/1)89%  (8/9)94%  (1.9/2)
getUDTs (String, String, String, int []): ResultSet 100% (1/1)89%  (41/46)71%  (5/7)
getExportedKeys (String, String, String): ResultSet 100% (1/1)92%  (58/63)83%  (10/12)
getImportedKeys (String, String, String): ResultSet 100% (1/1)92%  (58/63)83%  (10/12)
getPrimaryKeys (String, String, String): ResultSet 100% (1/1)92%  (58/63)83%  (10/12)
getProcedures (String, String, String): ResultSet 100% (1/1)93%  (63/68)85%  (11/13)
getTablePrivileges (String, String, String): ResultSet 100% (1/1)93%  (63/68)85%  (11/13)
getColumnPrivileges (String, String, String, String): ResultSet 100% (1/1)94%  (72/77)86%  (12/14)
getBestRowIdentifier (String, String, String, int, boolean): ResultSet 100% (1/1)94%  (74/79)86%  (12/14)
getFunctions (String): String 100% (1/1)94%  (77/82)90%  (18/20)
getProcedureColumns (String, String, String, String): ResultSet 100% (1/1)94%  (81/86)88%  (14/16)
getColumns (String, String, String, String): ResultSet 100% (1/1)94%  (85/90)88%  (15/17)
getIndexInfo (String, String, String, boolean, boolean): ResultSet 100% (1/1)95%  (86/91)87%  (13/15)
getCrossReference (String, String, String, String, String, String): ResultSet 100% (1/1)95%  (95/100)88%  (15/17)
getTables (String, String, String, String []): ResultSet 100% (1/1)96%  (130/135)91%  (21/23)
JdbcDatabaseMetaData (JdbcConnection, Trace, int): void 100% (1/1)100% (11/11)100% (4/4)
allProceduresAreCallable (): boolean 100% (1/1)100% (5/5)100% (2/2)
allTablesAreSelectable (): boolean 100% (1/1)100% (5/5)100% (2/2)
autoCommitFailureClosesAllResultSets (): boolean 100% (1/1)100% (5/5)100% (2/2)
checkClosed (): void 100% (1/1)100% (4/4)100% (2/2)
dataDefinitionCausesTransactionCommit (): boolean 100% (1/1)100% (5/5)100% (2/2)
dataDefinitionIgnoredInTransactions (): boolean 100% (1/1)100% (5/5)100% (2/2)
deletesAreDetected (int): boolean 100% (1/1)100% (7/7)100% (2/2)
doesMaxRowSizeIncludeBlobs (): boolean 100% (1/1)100% (5/5)100% (2/2)
generatedKeyAlwaysReturned (): boolean 100% (1/1)100% (2/2)100% (1/1)
getAttributes (String, String, String, String): ResultSet 100% (1/1)100% (4/4)100% (1/1)
getCatalogPattern (String): String 100% (1/1)100% (9/9)100% (1/1)
getCatalogSeparator (): String 100% (1/1)100% (5/5)100% (2/2)
getCatalogTerm (): String 100% (1/1)100% (5/5)100% (2/2)
getClientInfoProperties (): ResultSet 100% (1/1)100% (4/4)100% (1/1)
getConnection (): Connection 100% (1/1)100% (6/6)100% (2/2)
getDatabaseMajorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getDatabaseMinorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getDatabaseProductName (): String 100% (1/1)100% (5/5)100% (2/2)
getDatabaseProductVersion (): String 100% (1/1)100% (5/5)100% (2/2)
getDefaultTransactionIsolation (): int 100% (1/1)100% (5/5)100% (2/2)
getDriverMajorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getDriverMinorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getDriverName (): String 100% (1/1)100% (5/5)100% (2/2)
getDriverVersion (): String 100% (1/1)100% (5/5)100% (2/2)
getExtraNameCharacters (): String 100% (1/1)100% (5/5)100% (2/2)
getIdentifierQuoteString (): String 100% (1/1)100% (5/5)100% (2/2)
getJDBCMajorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getJDBCMinorVersion (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxBinaryLiteralLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxCatalogNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxCharLiteralLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnsInGroupBy (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnsInIndex (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnsInOrderBy (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnsInSelect (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxColumnsInTable (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxConnections (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxCursorNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxIndexLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxProcedureNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxRowSize (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxSchemaNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxStatementLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxStatements (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxTableNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxTablesInSelect (): int 100% (1/1)100% (5/5)100% (2/2)
getMaxUserNameLength (): int 100% (1/1)100% (5/5)100% (2/2)
getMode (): String 100% (1/1)100% (28/28)100% (8/8)
getNumericFunctions (): String 100% (1/1)100% (7/7)100% (2/2)
getPattern (String): String 100% (1/1)100% (6/6)100% (1/1)
getProcedureTerm (): String 100% (1/1)100% (5/5)100% (2/2)
getResultSetHoldability (): int 100% (1/1)100% (5/5)100% (2/2)
getRowIdLifetime (): RowIdLifetime 100% (1/1)100% (5/5)100% (2/2)
getSQLKeywords (): String 100% (1/1)100% (5/5)100% (2/2)
getSQLStateType (): int 100% (1/1)100% (5/5)100% (2/2)
getSchemaPattern (String): String 100% (1/1)100% (11/11)100% (1/1)
getSchemaTerm (): String 100% (1/1)100% (5/5)100% (2/2)
getSearchStringEscape (): String 100% (1/1)100% (5/5)100% (2/2)
getStringFunctions (): String 100% (1/1)100% (7/7)100% (2/2)
getSuperTypes (String, String, String): ResultSet 100% (1/1)100% (4/4)100% (1/1)
getSystemFunctions (): String 100% (1/1)100% (7/7)100% (2/2)
getTimeDateFunctions (): String 100% (1/1)100% (7/7)100% (2/2)
insertsAreDetected (int): boolean 100% (1/1)100% (7/7)100% (2/2)
isCatalogAtStart (): boolean 100% (1/1)100% (5/5)100% (2/2)
locatorsUpdateCopy (): boolean 100% (1/1)100% (5/5)100% (2/2)
nullPlusNonNullIsNull (): boolean 100% (1/1)100% (5/5)100% (2/2)
nullsAreSortedAtEnd (): boolean 100% (1/1)100% (5/5)100% (2/2)
nullsAreSortedAtStart (): boolean 100% (1/1)100% (5/5)100% (2/2)
nullsAreSortedHigh (): boolean 100% (1/1)100% (5/5)100% (2/2)
othersDeletesAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
othersInsertsAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
othersUpdatesAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
ownDeletesAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
ownInsertsAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
ownUpdatesAreVisible (int): boolean 100% (1/1)100% (7/7)100% (2/2)
storesLowerCaseIdentifiers (): boolean 100% (1/1)100% (14/14)100% (5/5)
storesLowerCaseQuotedIdentifiers (): boolean 100% (1/1)100% (14/14)100% (5/5)
storesMixedCaseIdentifiers (): boolean 100% (1/1)100% (5/5)100% (2/2)
storesMixedCaseQuotedIdentifiers (): boolean 100% (1/1)100% (14/14)100% (5/5)
storesUpperCaseIdentifiers (): boolean 100% (1/1)100% (14/14)100% (5/5)
storesUpperCaseQuotedIdentifiers (): boolean 100% (1/1)100% (14/14)100% (5/5)
supportsANSI92EntryLevelSQL (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsANSI92FullSQL (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsANSI92IntermediateSQL (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsAlterTableWithAddColumn (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsAlterTableWithDropColumn (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsBatchUpdates (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCatalogsInDataManipulation (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCatalogsInIndexDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCatalogsInPrivilegeDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCatalogsInProcedureCalls (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCatalogsInTableDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsColumnAliasing (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsConvert (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsConvert (int, int): boolean 100% (1/1)100% (21/21)100% (3/3)
supportsCoreSQLGrammar (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsCorrelatedSubqueries (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsDataDefinitionAndDataManipulationTransactions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsDataManipulationTransactionsOnly (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsDifferentTableCorrelationNames (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsExpressionsInOrderBy (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsExtendedSQLGrammar (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsFullOuterJoins (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsGetGeneratedKeys (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsGroupBy (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsGroupByBeyondSelect (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsGroupByUnrelated (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsIntegrityEnhancementFacility (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsLikeEscapeClause (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsLimitedOuterJoins (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsMinimumSQLGrammar (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsMixedCaseIdentifiers (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsMultipleOpenResults (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsMultipleResultSets (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsMultipleTransactions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsNamedParameters (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsNonNullableColumns (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOpenCursorsAcrossCommit (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOpenCursorsAcrossRollback (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOpenStatementsAcrossCommit (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOpenStatementsAcrossRollback (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOrderByUnrelated (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsOuterJoins (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsPositionedDelete (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsPositionedUpdate (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsResultSetConcurrency (int, int): boolean 100% (1/1)100% (26/26)100% (3/3)
supportsResultSetHoldability (int): boolean 100% (1/1)100% (12/12)100% (2/2)
supportsResultSetType (int): boolean 100% (1/1)100% (12/12)100% (2/2)
supportsSavepoints (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSchemasInDataManipulation (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSchemasInIndexDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSchemasInPrivilegeDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSchemasInProcedureCalls (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSchemasInTableDefinitions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSelectForUpdate (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsStatementPooling (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsStoredFunctionsUsingCallSyntax (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsStoredProcedures (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSubqueriesInComparisons (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSubqueriesInExists (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSubqueriesInIns (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsSubqueriesInQuantifieds (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsTableCorrelationNames (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsTransactionIsolationLevel (int): boolean 100% (1/1)100% (31/31)100% (8/8)
supportsTransactions (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsUnion (): boolean 100% (1/1)100% (5/5)100% (2/2)
supportsUnionAll (): boolean 100% (1/1)100% (5/5)100% (2/2)
updatesAreDetected (int): boolean 100% (1/1)100% (7/7)100% (2/2)
usesLocalFilePerTable (): boolean 100% (1/1)100% (5/5)100% (2/2)
usesLocalFiles (): boolean 100% (1/1)100% (5/5)100% (2/2)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.jdbc;
7 
8import java.sql.Connection;
9import java.sql.DatabaseMetaData;
10import java.sql.PreparedStatement;
11import java.sql.ResultSet;
12import java.sql.RowIdLifetime;
13import java.sql.SQLException;
14import org.h2.engine.Constants;
15import org.h2.engine.SysProperties;
16import org.h2.message.DbException;
17import org.h2.message.Trace;
18import org.h2.message.TraceObject;
19import org.h2.tools.SimpleResultSet;
20import org.h2.util.StatementBuilder;
21import org.h2.util.StringUtils;
22 
23/**
24 * Represents the meta data for a database.
25 */
26public class JdbcDatabaseMetaData extends TraceObject implements
27        DatabaseMetaData {
28 
29    private final JdbcConnection conn;
30    private String mode;
31 
32    JdbcDatabaseMetaData(JdbcConnection conn, Trace trace, int id) {
33        setTrace(trace, TraceObject.DATABASE_META_DATA, id);
34        this.conn = conn;
35    }
36 
37    /**
38     * Returns the major version of this driver.
39     *
40     * @return the major version number
41     */
42    @Override
43    public int getDriverMajorVersion() {
44        debugCodeCall("getDriverMajorVersion");
45        return Constants.VERSION_MAJOR;
46    }
47 
48    /**
49     * Returns the minor version of this driver.
50     *
51     * @return the minor version number
52     */
53    @Override
54    public int getDriverMinorVersion() {
55        debugCodeCall("getDriverMinorVersion");
56        return Constants.VERSION_MINOR;
57    }
58 
59    /**
60     * Gets the database product name.
61     *
62     * @return the product name ("H2")
63     */
64    @Override
65    public String getDatabaseProductName() {
66        debugCodeCall("getDatabaseProductName");
67        // This value must stay like that, see
68        // http://opensource.atlassian.com/projects/hibernate/browse/HHH-2682
69        return "H2";
70    }
71 
72    /**
73     * Gets the product version of the database.
74     *
75     * @return the product version
76     */
77    @Override
78    public String getDatabaseProductVersion() {
79        debugCodeCall("getDatabaseProductVersion");
80        return Constants.getFullVersion();
81    }
82 
83    /**
84     * Gets the name of the JDBC driver.
85     *
86     * @return the driver name ("H2 JDBC Driver")
87     */
88    @Override
89    public String getDriverName() {
90        debugCodeCall("getDriverName");
91        return "H2 JDBC Driver";
92    }
93 
94    /**
95     * Gets the version number of the driver. The format is
96     * [MajorVersion].[MinorVersion].
97     *
98     * @return the version number
99     */
100    @Override
101    public String getDriverVersion() {
102        debugCodeCall("getDriverVersion");
103        return Constants.getFullVersion();
104    }
105 
106    /**
107     * Gets the list of tables in the database. The result set is sorted by
108     * TABLE_TYPE, TABLE_SCHEM, and TABLE_NAME.
109     *
110     * <ul>
111     * <li>1 TABLE_CAT (String) table catalog </li>
112     * <li>2 TABLE_SCHEM (String) table schema </li>
113     * <li>3 TABLE_NAME (String) table name </li>
114     * <li>4 TABLE_TYPE (String) table type </li>
115     * <li>5 REMARKS (String) comment </li>
116     * <li>6 TYPE_CAT (String) always null </li>
117     * <li>7 TYPE_SCHEM (String) always null </li>
118     * <li>8 TYPE_NAME (String) always null </li>
119     * <li>9 SELF_REFERENCING_COL_NAME (String) always null </li>
120     * <li>10 REF_GENERATION (String) always null </li>
121     * <li>11 SQL (String) the create table statement or NULL for systems tables
122     * </li>
123     * </ul>
124     *
125     * @param catalogPattern null (to get all objects) or the catalog name
126     * @param schemaPattern null (to get all objects) or a schema name
127     *            (uppercase for unquoted names)
128     * @param tableNamePattern null (to get all objects) or a table name
129     *            (uppercase for unquoted names)
130     * @param types null or a list of table types
131     * @return the list of columns
132     * @throws SQLException if the connection is closed
133     */
134    @Override
135    public ResultSet getTables(String catalogPattern, String schemaPattern,
136            String tableNamePattern, String[] types) throws SQLException {
137        try {
138            if (isDebugEnabled()) {
139                debugCode("getTables(" + quote(catalogPattern) + ", " +
140                        quote(schemaPattern) + ", " + quote(tableNamePattern) +
141                        ", " + quoteArray(types) + ");");
142            }
143            checkClosed();
144            String tableType;
145            if (types != null && types.length > 0) {
146                StatementBuilder buff = new StatementBuilder("TABLE_TYPE IN(");
147                for (int i = 0; i < types.length; i++) {
148                    buff.appendExceptFirst(", ");
149                    buff.append('?');
150                }
151                tableType = buff.append(')').toString();
152            } else {
153                tableType = "TRUE";
154            }
155            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
156                    + "TABLE_CATALOG TABLE_CAT, "
157                    + "TABLE_SCHEMA TABLE_SCHEM, "
158                    + "TABLE_NAME, "
159                    + "TABLE_TYPE, "
160                    + "REMARKS, "
161                    + "TYPE_NAME TYPE_CAT, "
162                    + "TYPE_NAME TYPE_SCHEM, "
163                    + "TYPE_NAME, "
164                    + "TYPE_NAME SELF_REFERENCING_COL_NAME, "
165                    + "TYPE_NAME REF_GENERATION, "
166                    + "SQL "
167                    + "FROM INFORMATION_SCHEMA.TABLES "
168                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
169                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
170                    + "AND TABLE_NAME LIKE ? ESCAPE ? "
171                    + "AND (" + tableType + ") "
172                    + "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME");
173            prep.setString(1, getCatalogPattern(catalogPattern));
174            prep.setString(2, "\\");
175            prep.setString(3, getSchemaPattern(schemaPattern));
176            prep.setString(4, "\\");
177            prep.setString(5, getPattern(tableNamePattern));
178            prep.setString(6, "\\");
179            for (int i = 0; types != null && i < types.length; i++) {
180                prep.setString(7 + i, types[i]);
181            }
182            return prep.executeQuery();
183        } catch (Exception e) {
184            throw logAndConvert(e);
185        }
186    }
187 
188    /**
189     * Gets the list of columns. The result set is sorted by TABLE_SCHEM,
190     * TABLE_NAME, and ORDINAL_POSITION.
191     *
192     * <ul>
193     * <li>1 TABLE_CAT (String) table catalog </li>
194     * <li>2 TABLE_SCHEM (String) table schema </li>
195     * <li>3 TABLE_NAME (String) table name </li>
196     * <li>4 COLUMN_NAME (String) column name </li>
197     * <li>5 DATA_TYPE (short) data type (see java.sql.Types) </li>
198     * <li>6 TYPE_NAME (String) data type name ("INTEGER", "VARCHAR",...) </li>
199     * <li>7 COLUMN_SIZE (int) precision
200     *         (values larger than 2 GB are returned as 2 GB)</li>
201     * <li>8 BUFFER_LENGTH (int) unused </li>
202     * <li>9 DECIMAL_DIGITS (int) scale (0 for INTEGER and VARCHAR) </li>
203     * <li>10 NUM_PREC_RADIX (int) radix (always 10) </li>
204     * <li>11 NULLABLE (int) columnNoNulls or columnNullable</li>
205     * <li>12 REMARKS (String) comment (always empty) </li>
206     * <li>13 COLUMN_DEF (String) default value </li>
207     * <li>14 SQL_DATA_TYPE (int) unused </li>
208     * <li>15 SQL_DATETIME_SUB (int) unused </li>
209     * <li>16 CHAR_OCTET_LENGTH (int) unused </li>
210     * <li>17 ORDINAL_POSITION (int) the column index (1,2,...) </li>
211     * <li>18 IS_NULLABLE (String) "NO" or "YES" </li>
212     * <li>19 SCOPE_CATALOG (String) always null </li>
213     * <li>20 SCOPE_SCHEMA (String) always null </li>
214     * <li>21 SCOPE_TABLE (String) always null </li>
215     * <li>22 SOURCE_DATA_TYPE (short) null </li>
216     * <li>23 IS_AUTOINCREMENT (String) "NO" or "YES" </li>
217     * <li>24 SCOPE_CATLOG (String) always null (the typo is on purpose,
218     * for compatibility with the JDBC specification prior to 4.1)</li>
219     * </ul>
220     *
221     * @param catalogPattern null (to get all objects) or the catalog name
222     * @param schemaPattern null (to get all objects) or a schema name
223     *            (uppercase for unquoted names)
224     * @param tableNamePattern null (to get all objects) or a table name
225     *            (uppercase for unquoted names)
226     * @param columnNamePattern null (to get all objects) or a column name
227     *            (uppercase for unquoted names)
228     * @return the list of columns
229     * @throws SQLException if the connection is closed
230     */
231    @Override
232    public ResultSet getColumns(String catalogPattern, String schemaPattern,
233            String tableNamePattern, String columnNamePattern)
234            throws SQLException {
235        try {
236            if (isDebugEnabled()) {
237                debugCode("getColumns(" + quote(catalogPattern)+", "
238                        +quote(schemaPattern)+", "
239                        +quote(tableNamePattern)+", "
240                        +quote(columnNamePattern)+");");
241            }
242            checkClosed();
243            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
244                    + "TABLE_CATALOG TABLE_CAT, "
245                    + "TABLE_SCHEMA TABLE_SCHEM, "
246                    + "TABLE_NAME, "
247                    + "COLUMN_NAME, "
248                    + "DATA_TYPE, "
249                    + "TYPE_NAME, "
250                    + "CHARACTER_MAXIMUM_LENGTH COLUMN_SIZE, "
251                    + "CHARACTER_MAXIMUM_LENGTH BUFFER_LENGTH, "
252                    + "NUMERIC_SCALE DECIMAL_DIGITS, "
253                    + "NUMERIC_PRECISION_RADIX NUM_PREC_RADIX, "
254                    + "NULLABLE, "
255                    + "REMARKS, "
256                    + "COLUMN_DEFAULT COLUMN_DEF, "
257                    + "DATA_TYPE SQL_DATA_TYPE, "
258                    + "ZERO() SQL_DATETIME_SUB, "
259                    + "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH, "
260                    + "ORDINAL_POSITION, "
261                    + "IS_NULLABLE IS_NULLABLE, "
262                    + "CAST(SOURCE_DATA_TYPE AS VARCHAR) SCOPE_CATALOG, "
263                    + "CAST(SOURCE_DATA_TYPE AS VARCHAR) SCOPE_SCHEMA, "
264                    + "CAST(SOURCE_DATA_TYPE AS VARCHAR) SCOPE_TABLE, "
265                    + "SOURCE_DATA_TYPE, "
266                    + "CASE WHEN SEQUENCE_NAME IS NULL THEN "
267                    + "CAST(? AS VARCHAR) ELSE CAST(? AS VARCHAR) END IS_AUTOINCREMENT, "
268                    + "CAST(SOURCE_DATA_TYPE AS VARCHAR) SCOPE_CATLOG "
269                    + "FROM INFORMATION_SCHEMA.COLUMNS "
270                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
271                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
272                    + "AND TABLE_NAME LIKE ? ESCAPE ? "
273                    + "AND COLUMN_NAME LIKE ? ESCAPE ? "
274                    + "ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION");
275            prep.setString(1, "NO");
276            prep.setString(2, "YES");
277            prep.setString(3, getCatalogPattern(catalogPattern));
278            prep.setString(4, "\\");
279            prep.setString(5, getSchemaPattern(schemaPattern));
280            prep.setString(6, "\\");
281            prep.setString(7, getPattern(tableNamePattern));
282            prep.setString(8, "\\");
283            prep.setString(9, getPattern(columnNamePattern));
284            prep.setString(10, "\\");
285            return prep.executeQuery();
286        } catch (Exception e) {
287            throw logAndConvert(e);
288        }
289    }
290 
291    /**
292     * Gets the list of indexes for this database. The primary key index (if
293     * there is one) is also listed, with the name PRIMARY_KEY. The result set
294     * is sorted by NON_UNIQUE ('false' first), TYPE, TABLE_SCHEM, INDEX_NAME,
295     * and ORDINAL_POSITION.
296     *
297     * <ul>
298     * <li>1 TABLE_CAT (String) table catalog </li>
299     * <li>2 TABLE_SCHEM (String) table schema </li>
300     * <li>3 TABLE_NAME (String) table name </li>
301     * <li>4 NON_UNIQUE (boolean) 'true' if non-unique</li>
302     * <li>5 INDEX_QUALIFIER (String) index catalog </li>
303     * <li>6 INDEX_NAME (String) index name </li>
304     * <li>7 TYPE (short) the index type (always tableIndexOther) </li>
305     * <li>8 ORDINAL_POSITION (short) column index (1, 2, ...) </li>
306     * <li>9 COLUMN_NAME (String) column name </li>
307     * <li>10 ASC_OR_DESC (String) ascending or descending (always 'A') </li>
308     * <li>11 CARDINALITY (int) numbers of unique values </li>
309     * <li>12 PAGES (int) number of pages use (always 0) </li>
310     * <li>13 FILTER_CONDITION (String) filter condition (always empty) </li>
311     * <li>14 SORT_TYPE (int) the sort type bit map: 1=DESCENDING,
312     * 2=NULLS_FIRST, 4=NULLS_LAST </li>
313     * </ul>
314     *
315     * @param catalogPattern null or the catalog name
316     * @param schemaPattern null (to get all objects) or a schema name
317     *            (uppercase for unquoted names)
318     * @param tableName table name (must be specified)
319     * @param unique only unique indexes
320     * @param approximate is ignored
321     * @return the list of indexes and columns
322     * @throws SQLException if the connection is closed
323     */
324    @Override
325    public ResultSet getIndexInfo(String catalogPattern, String schemaPattern,
326            String tableName, boolean unique, boolean approximate)
327            throws SQLException {
328        try {
329            if (isDebugEnabled()) {
330                debugCode("getIndexInfo(" + quote(catalogPattern) + ", " +
331                        quote(schemaPattern) + ", " + quote(tableName) + ", " +
332                        unique + ", " + approximate + ");");
333            }
334            String uniqueCondition;
335            if (unique) {
336                uniqueCondition = "NON_UNIQUE=FALSE";
337            } else {
338                uniqueCondition = "TRUE";
339            }
340            checkClosed();
341            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
342                    + "TABLE_CATALOG TABLE_CAT, "
343                    + "TABLE_SCHEMA TABLE_SCHEM, "
344                    + "TABLE_NAME, "
345                    + "NON_UNIQUE, "
346                    + "TABLE_CATALOG INDEX_QUALIFIER, "
347                    + "INDEX_NAME, "
348                    + "INDEX_TYPE TYPE, "
349                    + "ORDINAL_POSITION, "
350                    + "COLUMN_NAME, "
351                    + "ASC_OR_DESC, "
352                    // TODO meta data for number of unique values in an index
353                    + "CARDINALITY, "
354                    + "PAGES, "
355                    + "FILTER_CONDITION, "
356                    + "SORT_TYPE "
357                    + "FROM INFORMATION_SCHEMA.INDEXES "
358                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
359                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
360                    + "AND (" + uniqueCondition + ") "
361                    + "AND TABLE_NAME = ? "
362                    + "ORDER BY NON_UNIQUE, TYPE, TABLE_SCHEM, INDEX_NAME, ORDINAL_POSITION");
363            prep.setString(1, getCatalogPattern(catalogPattern));
364            prep.setString(2, "\\");
365            prep.setString(3, getSchemaPattern(schemaPattern));
366            prep.setString(4, "\\");
367            prep.setString(5, tableName);
368            return prep.executeQuery();
369        } catch (Exception e) {
370            throw logAndConvert(e);
371        }
372    }
373 
374    /**
375     * Gets the primary key columns for a table. The result set is sorted by
376     * TABLE_SCHEM, and COLUMN_NAME (and not by KEY_SEQ).
377     *
378     * <ul>
379     * <li>1 TABLE_CAT (String) table catalog</li>
380     * <li>2 TABLE_SCHEM (String) table schema</li>
381     * <li>3 TABLE_NAME (String) table name</li>
382     * <li>4 COLUMN_NAME (String) column name</li>
383     * <li>5 KEY_SEQ (short) the column index of this column (1,2,...)</li>
384     * <li>6 PK_NAME (String) the name of the primary key index</li>
385     * </ul>
386     *
387     * @param catalogPattern null or the catalog name
388     * @param schemaPattern null (to get all objects) or a schema name
389     *            (uppercase for unquoted names)
390     * @param tableName table name (must be specified)
391     * @return the list of primary key columns
392     * @throws SQLException if the connection is closed
393     */
394    @Override
395    public ResultSet getPrimaryKeys(String catalogPattern,
396            String schemaPattern, String tableName) throws SQLException {
397        try {
398            if (isDebugEnabled()) {
399                debugCode("getPrimaryKeys("
400                        +quote(catalogPattern)+", "
401                        +quote(schemaPattern)+", "
402                        +quote(tableName)+");");
403            }
404            checkClosed();
405            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
406                    + "TABLE_CATALOG TABLE_CAT, "
407                    + "TABLE_SCHEMA TABLE_SCHEM, "
408                    + "TABLE_NAME, "
409                    + "COLUMN_NAME, "
410                    + "ORDINAL_POSITION KEY_SEQ, "
411                    + "IFNULL(CONSTRAINT_NAME, INDEX_NAME) PK_NAME "
412                    + "FROM INFORMATION_SCHEMA.INDEXES "
413                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
414                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
415                    + "AND TABLE_NAME = ? "
416                    + "AND PRIMARY_KEY = TRUE "
417                    + "ORDER BY COLUMN_NAME");
418            prep.setString(1, getCatalogPattern(catalogPattern));
419            prep.setString(2, "\\");
420            prep.setString(3, getSchemaPattern(schemaPattern));
421            prep.setString(4, "\\");
422            prep.setString(5, tableName);
423            return prep.executeQuery();
424        } catch (Exception e) {
425            throw logAndConvert(e);
426        }
427    }
428 
429    /**
430     * Checks if all procedures callable.
431     *
432     * @return true
433     */
434    @Override
435    public boolean allProceduresAreCallable() {
436        debugCodeCall("allProceduresAreCallable");
437        return true;
438    }
439 
440    /**
441     * Checks if it possible to query all tables returned by getTables.
442     *
443     * @return true
444     */
445    @Override
446    public boolean allTablesAreSelectable() {
447        debugCodeCall("allTablesAreSelectable");
448        return true;
449    }
450 
451    /**
452     * Returns the database URL for this connection.
453     *
454     * @return the url
455     */
456    @Override
457    public String getURL() throws SQLException {
458        try {
459            debugCodeCall("getURL");
460            return conn.getURL();
461        } catch (Exception e) {
462            throw logAndConvert(e);
463        }
464    }
465 
466    /**
467     * Returns the user name as passed to DriverManager.getConnection(url, user,
468     * password).
469     *
470     * @return the user name
471     */
472    @Override
473    public String getUserName() throws SQLException {
474        try {
475            debugCodeCall("getUserName");
476            return conn.getUser();
477        } catch (Exception e) {
478            throw logAndConvert(e);
479        }
480    }
481 
482    /**
483     * Returns the same as Connection.isReadOnly().
484     *
485     * @return if read only optimization is switched on
486     */
487    @Override
488    public boolean isReadOnly() throws SQLException {
489        try {
490            debugCodeCall("isReadOnly");
491            return conn.isReadOnly();
492        } catch (Exception e) {
493            throw logAndConvert(e);
494        }
495    }
496 
497    /**
498     * Checks if NULL is sorted high (bigger than anything that is not null).
499     *
500     * @return false by default; true if the system property h2.sortNullsHigh is
501     *         set to true
502     */
503    @Override
504    public boolean nullsAreSortedHigh() {
505        debugCodeCall("nullsAreSortedHigh");
506        return SysProperties.SORT_NULLS_HIGH;
507    }
508 
509    /**
510     * Checks if NULL is sorted low (smaller than anything that is not null).
511     *
512     * @return true by default; false if the system property h2.sortNullsHigh is
513     *         set to true
514     */
515    @Override
516    public boolean nullsAreSortedLow() {
517        debugCodeCall("nullsAreSortedLow");
518        return !SysProperties.SORT_NULLS_HIGH;
519    }
520 
521    /**
522     * Checks if NULL is sorted at the beginning (no matter if ASC or DESC is
523     * used).
524     *
525     * @return false
526     */
527    @Override
528    public boolean nullsAreSortedAtStart() {
529        debugCodeCall("nullsAreSortedAtStart");
530        return false;
531    }
532 
533    /**
534     * Checks if NULL is sorted at the end (no matter if ASC or DESC is used).
535     *
536     * @return false
537     */
538    @Override
539    public boolean nullsAreSortedAtEnd() {
540        debugCodeCall("nullsAreSortedAtEnd");
541        return false;
542    }
543 
544    /**
545     * Returns the connection that created this object.
546     *
547     * @return the connection
548     */
549    @Override
550    public Connection getConnection() {
551        debugCodeCall("getConnection");
552        return conn;
553    }
554 
555    /**
556     * Gets the list of procedures. The result set is sorted by PROCEDURE_SCHEM,
557     * PROCEDURE_NAME, and NUM_INPUT_PARAMS. There are potentially multiple
558     * procedures with the same name, each with a different number of input
559     * parameters.
560     *
561     * <ul>
562     * <li>1 PROCEDURE_CAT (String) catalog </li>
563     * <li>2 PROCEDURE_SCHEM (String) schema </li>
564     * <li>3 PROCEDURE_NAME (String) name </li>
565     * <li>4 NUM_INPUT_PARAMS (int) the number of arguments </li>
566     * <li>5 NUM_OUTPUT_PARAMS (int) for future use, always 0 </li>
567     * <li>6 NUM_RESULT_SETS (int) for future use, always 0 </li>
568     * <li>7 REMARKS (String) description </li>
569     * <li>8 PROCEDURE_TYPE (short) if this procedure returns a result
570     * (procedureNoResult or procedureReturnsResult) </li>
571     * <li>9 SPECIFIC_NAME (String) name </li>
572     * </ul>
573     *
574     * @param catalogPattern null or the catalog name
575     * @param schemaPattern null (to get all objects) or a schema name
576     *            (uppercase for unquoted names)
577     * @param procedureNamePattern the procedure name pattern
578     * @return the procedures
579     * @throws SQLException if the connection is closed
580     */
581    @Override
582    public ResultSet getProcedures(String catalogPattern, String schemaPattern,
583            String procedureNamePattern) throws SQLException {
584        try {
585            if (isDebugEnabled()) {
586                debugCode("getProcedures("
587                        +quote(catalogPattern)+", "
588                        +quote(schemaPattern)+", "
589                        +quote(procedureNamePattern)+");");
590            }
591            checkClosed();
592            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
593                    + "ALIAS_CATALOG PROCEDURE_CAT, "
594                    + "ALIAS_SCHEMA PROCEDURE_SCHEM, "
595                    + "ALIAS_NAME PROCEDURE_NAME, "
596                    + "COLUMN_COUNT NUM_INPUT_PARAMS, "
597                    + "ZERO() NUM_OUTPUT_PARAMS, "
598                    + "ZERO() NUM_RESULT_SETS, "
599                    + "REMARKS, "
600                    + "RETURNS_RESULT PROCEDURE_TYPE, "
601                    + "ALIAS_NAME SPECIFIC_NAME "
602                    + "FROM INFORMATION_SCHEMA.FUNCTION_ALIASES "
603                    + "WHERE ALIAS_CATALOG LIKE ? ESCAPE ? "
604                    + "AND ALIAS_SCHEMA LIKE ? ESCAPE ? "
605                    + "AND ALIAS_NAME LIKE ? ESCAPE ? "
606                    + "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS");
607            prep.setString(1, getCatalogPattern(catalogPattern));
608            prep.setString(2, "\\");
609            prep.setString(3, getSchemaPattern(schemaPattern));
610            prep.setString(4, "\\");
611            prep.setString(5, getPattern(procedureNamePattern));
612            prep.setString(6, "\\");
613            return prep.executeQuery();
614        } catch (Exception e) {
615            throw logAndConvert(e);
616        }
617    }
618 
619    /**
620     * Gets the list of procedure columns. The result set is sorted by
621     * PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS, and POS.
622     * There are potentially multiple procedures with the same name, each with a
623     * different number of input parameters.
624     *
625     * <ul>
626     * <li>1 PROCEDURE_CAT (String) catalog </li>
627     * <li>2 PROCEDURE_SCHEM (String) schema </li>
628     * <li>3 PROCEDURE_NAME (String) name </li>
629     * <li>4 COLUMN_NAME (String) column name </li>
630     * <li>5 COLUMN_TYPE (short) column type
631     * (always DatabaseMetaData.procedureColumnIn)</li>
632     * <li>6 DATA_TYPE (short) sql type </li>
633     * <li>7 TYPE_NAME (String) type name </li>
634     * <li>8 PRECISION (int) precision </li>
635     * <li>9 LENGTH (int) length </li>
636     * <li>10 SCALE (short) scale </li>
637     * <li>11 RADIX (int) always 10 </li>
638     * <li>12 NULLABLE (short) nullable
639     * (DatabaseMetaData.columnNoNulls for primitive data types,
640     * DatabaseMetaData.columnNullable otherwise)</li>
641     * <li>13 REMARKS (String) description </li>
642     * <li>14 COLUMN_DEF (String) always null </li>
643     * <li>15 SQL_DATA_TYPE (int) for future use, always 0 </li>
644     * <li>16 SQL_DATETIME_SUB (int) for future use, always 0 </li>
645     * <li>17 CHAR_OCTET_LENGTH (int) always null </li>
646     * <li>18 ORDINAL_POSITION (int) the parameter index
647     * starting from 1 (0 is the return value) </li>
648     * <li>19 IS_NULLABLE (String) always "YES" </li>
649     * <li>20 SPECIFIC_NAME (String) name </li>
650     * </ul>
651     *
652     * @param catalogPattern null or the catalog name
653     * @param schemaPattern null (to get all objects) or a schema name
654     *            (uppercase for unquoted names)
655     * @param procedureNamePattern the procedure name pattern
656     * @param columnNamePattern the procedure name pattern
657     * @return the procedure columns
658     * @throws SQLException if the connection is closed
659     */
660    @Override
661    public ResultSet getProcedureColumns(String catalogPattern,
662            String schemaPattern, String procedureNamePattern,
663            String columnNamePattern) throws SQLException {
664        try {
665            if (isDebugEnabled()) {
666                debugCode("getProcedureColumns("
667                        +quote(catalogPattern)+", "
668                        +quote(schemaPattern)+", "
669                        +quote(procedureNamePattern)+", "
670                        +quote(columnNamePattern)+");");
671            }
672            checkClosed();
673            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
674                    + "ALIAS_CATALOG PROCEDURE_CAT, "
675                    + "ALIAS_SCHEMA PROCEDURE_SCHEM, "
676                    + "ALIAS_NAME PROCEDURE_NAME, "
677                    + "COLUMN_NAME, "
678                    + "COLUMN_TYPE, "
679                    + "DATA_TYPE, "
680                    + "TYPE_NAME, "
681                    + "PRECISION, "
682                    + "PRECISION LENGTH, "
683                    + "SCALE, "
684                    + "RADIX, "
685                    + "NULLABLE, "
686                    + "REMARKS, "
687                    + "COLUMN_DEFAULT COLUMN_DEF, "
688                    + "ZERO() SQL_DATA_TYPE, "
689                    + "ZERO() SQL_DATETIME_SUB, "
690                    + "ZERO() CHAR_OCTET_LENGTH, "
691                    + "POS ORDINAL_POSITION, "
692                    + "? IS_NULLABLE, "
693                    + "ALIAS_NAME SPECIFIC_NAME "
694                    + "FROM INFORMATION_SCHEMA.FUNCTION_COLUMNS "
695                    + "WHERE ALIAS_CATALOG LIKE ? ESCAPE ? "
696                    + "AND ALIAS_SCHEMA LIKE ? ESCAPE ? "
697                    + "AND ALIAS_NAME LIKE ? ESCAPE ? "
698                    + "AND COLUMN_NAME LIKE ? ESCAPE ? "
699                    + "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, ORDINAL_POSITION");
700            prep.setString(1, "YES");
701            prep.setString(2, getCatalogPattern(catalogPattern));
702            prep.setString(3, "\\");
703            prep.setString(4, getSchemaPattern(schemaPattern));
704            prep.setString(5, "\\");
705            prep.setString(6, getPattern(procedureNamePattern));
706            prep.setString(7, "\\");
707            prep.setString(8, getPattern(columnNamePattern));
708            prep.setString(9, "\\");
709            return prep.executeQuery();
710        } catch (Exception e) {
711            throw logAndConvert(e);
712        }
713    }
714 
715    /**
716     * Gets the list of schemas.
717     * The result set is sorted by TABLE_SCHEM.
718     *
719     * <ul>
720     * <li>1 TABLE_SCHEM (String) schema name
721     * </li><li>2 TABLE_CATALOG (String) catalog name
722     * </li><li>3 IS_DEFAULT (boolean) if this is the default schema
723     * </li></ul>
724     *
725     * @return the schema list
726     * @throws SQLException if the connection is closed
727     */
728    @Override
729    public ResultSet getSchemas() throws SQLException {
730        try {
731            debugCodeCall("getSchemas");
732            checkClosed();
733            PreparedStatement prep = conn
734                    .prepareAutoCloseStatement("SELECT "
735                            + "SCHEMA_NAME TABLE_SCHEM, "
736                            + "CATALOG_NAME TABLE_CATALOG, "
737                            +" IS_DEFAULT "
738                            + "FROM INFORMATION_SCHEMA.SCHEMATA "
739                            + "ORDER BY SCHEMA_NAME");
740            return prep.executeQuery();
741        } catch (Exception e) {
742            throw logAndConvert(e);
743        }
744    }
745 
746    /**
747     * Gets the list of catalogs.
748     * The result set is sorted by TABLE_CAT.
749     *
750     * <ul>
751     * <li>1 TABLE_CAT (String) catalog name
752     * </li></ul>
753     *
754     * @return the catalog list
755     * @throws SQLException if the connection is closed
756     */
757    @Override
758    public ResultSet getCatalogs() throws SQLException {
759        try {
760            debugCodeCall("getCatalogs");
761            checkClosed();
762            PreparedStatement prep = conn.prepareAutoCloseStatement(
763                    "SELECT CATALOG_NAME TABLE_CAT "
764                    + "FROM INFORMATION_SCHEMA.CATALOGS");
765            return prep.executeQuery();
766        } catch (Exception e) {
767            throw logAndConvert(e);
768        }
769    }
770 
771    /**
772     * Gets the list of table types. This call returns a result set with three
773     * records: "SYSTEM TABLE", "TABLE", "and "VIEW".
774     * The result set is sorted by TABLE_TYPE.
775     *
776     * <ul>
777     * <li>1 TABLE_TYPE (String) table type
778     * </li></ul>
779     *
780     * @return the table types
781     * @throws SQLException if the connection is closed
782     */
783    @Override
784    public ResultSet getTableTypes() throws SQLException {
785        try {
786            debugCodeCall("getTableTypes");
787            checkClosed();
788            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
789                    + "TYPE TABLE_TYPE "
790                    + "FROM INFORMATION_SCHEMA.TABLE_TYPES "
791                    + "ORDER BY TABLE_TYPE");
792            return prep.executeQuery();
793        } catch (Exception e) {
794            throw logAndConvert(e);
795        }
796    }
797 
798    /**
799     * Gets the list of column privileges. The result set is sorted by
800     * COLUMN_NAME and PRIVILEGE
801     *
802     * <ul>
803     * <li>1 TABLE_CAT (String) table catalog</li>
804     * <li>2 TABLE_SCHEM (String) table schema</li>
805     * <li>3 TABLE_NAME (String) table name</li>
806     * <li>4 COLUMN_NAME (String) column name</li>
807     * <li>5 GRANTOR (String) grantor of access</li>
808     * <li>6 GRANTEE (String) grantee of access</li>
809     * <li>7 PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
810     * (only one per row)</li>
811     * <li>8 IS_GRANTABLE (String) YES means the grantee can grant access to
812     * others</li>
813     * </ul>
814     *
815     * @param catalogPattern null (to get all objects) or the catalog name
816     * @param schemaPattern null (to get all objects) or a schema name
817     *            (uppercase for unquoted names)
818     * @param table a table name (uppercase for unquoted names)
819     * @param columnNamePattern null (to get all objects) or a column name
820     *            (uppercase for unquoted names)
821     * @return the list of privileges
822     * @throws SQLException if the connection is closed
823     */
824    @Override
825    public ResultSet getColumnPrivileges(String catalogPattern,
826            String schemaPattern, String table, String columnNamePattern)
827            throws SQLException {
828        try {
829            if (isDebugEnabled()) {
830                debugCode("getColumnPrivileges("
831                        +quote(catalogPattern)+", "
832                        +quote(schemaPattern)+", "
833                        +quote(table)+", "
834                        +quote(columnNamePattern)+");");
835            }
836            checkClosed();
837            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
838                    + "TABLE_CATALOG TABLE_CAT, "
839                    + "TABLE_SCHEMA TABLE_SCHEM, "
840                    + "TABLE_NAME, "
841                    + "COLUMN_NAME, "
842                    + "GRANTOR, "
843                    + "GRANTEE, "
844                    + "PRIVILEGE_TYPE PRIVILEGE, "
845                    + "IS_GRANTABLE "
846                    + "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES "
847                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
848                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
849                    + "AND TABLE_NAME = ? "
850                    + "AND COLUMN_NAME LIKE ? ESCAPE ? "
851                    + "ORDER BY COLUMN_NAME, PRIVILEGE");
852            prep.setString(1, getCatalogPattern(catalogPattern));
853            prep.setString(2, "\\");
854            prep.setString(3, getSchemaPattern(schemaPattern));
855            prep.setString(4, "\\");
856            prep.setString(5, table);
857            prep.setString(6, getPattern(columnNamePattern));
858            prep.setString(7, "\\");
859            return prep.executeQuery();
860        } catch (Exception e) {
861            throw logAndConvert(e);
862        }
863    }
864 
865    /**
866     * Gets the list of table privileges. The result set is sorted by
867     * TABLE_SCHEM, TABLE_NAME, and PRIVILEGE.
868     *
869     * <ul>
870     * <li>1 TABLE_CAT (String) table catalog </li>
871     * <li>2 TABLE_SCHEM (String) table schema </li>
872     * <li>3 TABLE_NAME (String) table name </li>
873     * <li>4 GRANTOR (String) grantor of access </li>
874     * <li>5 GRANTEE (String) grantee of access </li>
875     * <li>6 PRIVILEGE (String) SELECT, INSERT, UPDATE, DELETE or REFERENCES
876     * (only one per row) </li>
877     * <li>7 IS_GRANTABLE (String) YES means the grantee can grant access to
878     * others </li>
879     * </ul>
880     *
881     * @param catalogPattern null (to get all objects) or the catalog name
882     * @param schemaPattern null (to get all objects) or a schema name
883     *            (uppercase for unquoted names)
884     * @param tableNamePattern null (to get all objects) or a table name
885     *            (uppercase for unquoted names)
886     * @return the list of privileges
887     * @throws SQLException if the connection is closed
888     */
889    @Override
890    public ResultSet getTablePrivileges(String catalogPattern,
891            String schemaPattern, String tableNamePattern) throws SQLException {
892        try {
893            if (isDebugEnabled()) {
894                debugCode("getTablePrivileges("
895                        +quote(catalogPattern)+", "
896                        +quote(schemaPattern)+", "
897                        +quote(tableNamePattern)+");");
898            }
899            checkClosed();
900            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
901                    + "TABLE_CATALOG TABLE_CAT, "
902                    + "TABLE_SCHEMA TABLE_SCHEM, "
903                    + "TABLE_NAME, "
904                    + "GRANTOR, "
905                    + "GRANTEE, "
906                    + "PRIVILEGE_TYPE PRIVILEGE, "
907                    + "IS_GRANTABLE "
908                    + "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES "
909                    + "WHERE TABLE_CATALOG LIKE ? ESCAPE ? "
910                    + "AND TABLE_SCHEMA LIKE ? ESCAPE ? "
911                    + "AND TABLE_NAME LIKE ? ESCAPE ? "
912                    + "ORDER BY TABLE_SCHEM, TABLE_NAME, PRIVILEGE");
913            prep.setString(1, getCatalogPattern(catalogPattern));
914            prep.setString(2, "\\");
915            prep.setString(3, getSchemaPattern(schemaPattern));
916            prep.setString(4, "\\");
917            prep.setString(5, getPattern(tableNamePattern));
918            prep.setString(6, "\\");
919            return prep.executeQuery();
920        } catch (Exception e) {
921            throw logAndConvert(e);
922        }
923    }
924 
925    /**
926     * Gets the list of columns that best identifier a row in a table.
927     * The list is ordered by SCOPE.
928     *
929     * <ul>
930     * <li>1 SCOPE (short) scope of result (always bestRowSession)
931     * </li><li>2 COLUMN_NAME (String) column name
932     * </li><li>3 DATA_TYPE (short) SQL data type, see also java.sql.Types
933     * </li><li>4 TYPE_NAME (String) type name
934     * </li><li>5 COLUMN_SIZE (int) precision
935     *         (values larger than 2 GB are returned as 2 GB)
936     * </li><li>6 BUFFER_LENGTH (int) unused
937     * </li><li>7 DECIMAL_DIGITS (short) scale
938     * </li><li>8 PSEUDO_COLUMN (short) (always bestRowNotPseudo)
939     * </li></ul>
940     *
941     * @param catalogPattern null (to get all objects) or the catalog name
942     * @param schemaPattern null (to get all objects) or a schema name
943     *            (uppercase for unquoted names)
944     * @param tableName table name (must be specified)
945     * @param scope ignored
946     * @param nullable ignored
947     * @return the primary key index
948     * @throws SQLException if the connection is closed
949     */
950    @Override
951    public ResultSet getBestRowIdentifier(String catalogPattern,
952            String schemaPattern, String tableName, int scope, boolean nullable)
953            throws SQLException {
954        try {
955            if (isDebugEnabled()) {
956                debugCode("getBestRowIdentifier("
957                        +quote(catalogPattern)+", "
958                        +quote(schemaPattern)+", "
959                        +quote(tableName)+", "
960                        +scope+", "+nullable+");");
961            }
962            checkClosed();
963            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
964                    + "CAST(? AS SMALLINT) SCOPE, "
965                    + "C.COLUMN_NAME, "
966                    + "C.DATA_TYPE, "
967                    + "C.TYPE_NAME, "
968                    + "C.CHARACTER_MAXIMUM_LENGTH COLUMN_SIZE, "
969                    + "C.CHARACTER_MAXIMUM_LENGTH BUFFER_LENGTH, "
970                    + "CAST(C.NUMERIC_SCALE AS SMALLINT) DECIMAL_DIGITS, "
971                    + "CAST(? AS SMALLINT) PSEUDO_COLUMN "
972                    + "FROM INFORMATION_SCHEMA.INDEXES I, "
973                    +" INFORMATION_SCHEMA.COLUMNS C "
974                    + "WHERE C.TABLE_NAME = I.TABLE_NAME "
975                    + "AND C.COLUMN_NAME = I.COLUMN_NAME "
976                    + "AND C.TABLE_CATALOG LIKE ? ESCAPE ? "
977                    + "AND C.TABLE_SCHEMA LIKE ? ESCAPE ? "
978                    + "AND C.TABLE_NAME = ? "
979                    + "AND I.PRIMARY_KEY = TRUE "
980                    + "ORDER BY SCOPE");
981            // SCOPE
982            prep.setInt(1, DatabaseMetaData.bestRowSession);
983            // PSEUDO_COLUMN
984            prep.setInt(2, DatabaseMetaData.bestRowNotPseudo);
985            prep.setString(3, getCatalogPattern(catalogPattern));
986            prep.setString(4, "\\");
987            prep.setString(5, getSchemaPattern(schemaPattern));
988            prep.setString(6, "\\");
989            prep.setString(7, tableName);
990            return prep.executeQuery();
991        } catch (Exception e) {
992            throw logAndConvert(e);
993        }
994    }
995 
996    /**
997     * Get the list of columns that are update when any value is updated.
998     * The result set is always empty.
999     *
1000     * <ul>
1001     * <li>1 SCOPE (int) not used
1002     * </li><li>2 COLUMN_NAME (String) column name
1003     * </li><li>3 DATA_TYPE (int) SQL data type - see also java.sql.Types
1004     * </li><li>4 TYPE_NAME (String) data type name
1005     * </li><li>5 COLUMN_SIZE (int) precision
1006     *         (values larger than 2 GB are returned as 2 GB)
1007     * </li><li>6 BUFFER_LENGTH (int) length (bytes)
1008     * </li><li>7 DECIMAL_DIGITS (int) scale
1009     * </li><li>8 PSEUDO_COLUMN (int) is this column a pseudo column
1010     * </li></ul>
1011     *
1012     * @param catalog null (to get all objects) or the catalog name
1013     * @param schema null (to get all objects) or a schema name
1014     * @param tableName table name (must be specified)
1015     * @return an empty result set
1016     * @throws SQLException if the connection is closed
1017     */
1018    @Override
1019    public ResultSet getVersionColumns(String catalog, String schema,
1020            String tableName) throws SQLException {
1021        try {
1022            if (isDebugEnabled()) {
1023                debugCode("getVersionColumns("
1024                        +quote(catalog)+", "
1025                        +quote(schema)+", "
1026                        +quote(tableName)+");");
1027            }
1028            checkClosed();
1029            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1030                    + "ZERO() SCOPE, "
1031                    + "COLUMN_NAME, "
1032                    + "CAST(DATA_TYPE AS INT) DATA_TYPE, "
1033                    + "TYPE_NAME, "
1034                    + "NUMERIC_PRECISION COLUMN_SIZE, "
1035                    + "NUMERIC_PRECISION BUFFER_LENGTH, "
1036                    + "NUMERIC_PRECISION DECIMAL_DIGITS, "
1037                    + "ZERO() PSEUDO_COLUMN "
1038                    + "FROM INFORMATION_SCHEMA.COLUMNS "
1039                    + "WHERE FALSE");
1040            return prep.executeQuery();
1041        } catch (Exception e) {
1042            throw logAndConvert(e);
1043        }
1044    }
1045 
1046    /**
1047     * Gets the list of primary key columns that are referenced by a table. The
1048     * result set is sorted by PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
1049     * FK_NAME, KEY_SEQ.
1050     *
1051     * <ul>
1052     * <li>1 PKTABLE_CAT (String) primary catalog </li>
1053     * <li>2 PKTABLE_SCHEM (String) primary schema </li>
1054     * <li>3 PKTABLE_NAME (String) primary table </li>
1055     * <li>4 PKCOLUMN_NAME (String) primary column </li>
1056     * <li>5 FKTABLE_CAT (String) foreign catalog </li>
1057     * <li>6 FKTABLE_SCHEM (String) foreign schema </li>
1058     * <li>7 FKTABLE_NAME (String) foreign table </li>
1059     * <li>8 FKCOLUMN_NAME (String) foreign column </li>
1060     * <li>9 KEY_SEQ (short) sequence number (1, 2, ...) </li>
1061     * <li>10 UPDATE_RULE (short) action on update (see
1062     * DatabaseMetaData.importedKey...) </li>
1063     * <li>11 DELETE_RULE (short) action on delete (see
1064     * DatabaseMetaData.importedKey...) </li>
1065     * <li>12 FK_NAME (String) foreign key name </li>
1066     * <li>13 PK_NAME (String) primary key name </li>
1067     * <li>14 DEFERRABILITY (short) deferrable or not (always
1068     * importedKeyNotDeferrable) </li>
1069     * </ul>
1070     *
1071     * @param catalogPattern null (to get all objects) or the catalog name
1072     * @param schemaPattern the schema name of the foreign table
1073     * @param tableName the name of the foreign table
1074     * @return the result set
1075     * @throws SQLException if the connection is closed
1076     */
1077    @Override
1078    public ResultSet getImportedKeys(String catalogPattern,
1079            String schemaPattern, String tableName) throws SQLException {
1080        try {
1081            if (isDebugEnabled()) {
1082                debugCode("getImportedKeys("
1083                        +quote(catalogPattern)+", "
1084                        +quote(schemaPattern)+", "
1085                        +quote(tableName)+");");
1086            }
1087            checkClosed();
1088            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1089                    + "PKTABLE_CATALOG PKTABLE_CAT, "
1090                    + "PKTABLE_SCHEMA PKTABLE_SCHEM, "
1091                    + "PKTABLE_NAME PKTABLE_NAME, "
1092                    + "PKCOLUMN_NAME, "
1093                    + "FKTABLE_CATALOG FKTABLE_CAT, "
1094                    + "FKTABLE_SCHEMA FKTABLE_SCHEM, "
1095                    + "FKTABLE_NAME, "
1096                    + "FKCOLUMN_NAME, "
1097                    + "ORDINAL_POSITION KEY_SEQ, "
1098                    + "UPDATE_RULE, "
1099                    + "DELETE_RULE, "
1100                    + "FK_NAME, "
1101                    + "PK_NAME, "
1102                    + "DEFERRABILITY "
1103                    + "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
1104                    + "WHERE FKTABLE_CATALOG LIKE ? ESCAPE ? "
1105                    + "AND FKTABLE_SCHEMA LIKE ? ESCAPE ? "
1106                    + "AND FKTABLE_NAME = ? "
1107                    + "ORDER BY PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME, FK_NAME, KEY_SEQ");
1108            prep.setString(1, getCatalogPattern(catalogPattern));
1109            prep.setString(2, "\\");
1110            prep.setString(3, getSchemaPattern(schemaPattern));
1111            prep.setString(4, "\\");
1112            prep.setString(5, tableName);
1113            return prep.executeQuery();
1114        } catch (Exception e) {
1115            throw logAndConvert(e);
1116        }
1117    }
1118 
1119    /**
1120     * Gets the list of foreign key columns that reference a table. The result
1121     * set is sorted by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME,
1122     * KEY_SEQ.
1123     *
1124     * <ul>
1125     * <li>1 PKTABLE_CAT (String) primary catalog </li>
1126     * <li>2 PKTABLE_SCHEM (String) primary schema </li>
1127     * <li>3 PKTABLE_NAME (String) primary table </li>
1128     * <li>4 PKCOLUMN_NAME (String) primary column </li>
1129     * <li>5 FKTABLE_CAT (String) foreign catalog </li>
1130     * <li>6 FKTABLE_SCHEM (String) foreign schema </li>
1131     * <li>7 FKTABLE_NAME (String) foreign table </li>
1132     * <li>8 FKCOLUMN_NAME (String) foreign column </li>
1133     * <li>9 KEY_SEQ (short) sequence number (1,2,...) </li>
1134     * <li>10 UPDATE_RULE (short) action on update (see
1135     * DatabaseMetaData.importedKey...) </li>
1136     * <li>11 DELETE_RULE (short) action on delete (see
1137     * DatabaseMetaData.importedKey...) </li>
1138     * <li>12 FK_NAME (String) foreign key name </li>
1139     * <li>13 PK_NAME (String) primary key name </li>
1140     * <li>14 DEFERRABILITY (short) deferrable or not (always
1141     * importedKeyNotDeferrable) </li>
1142     * </ul>
1143     *
1144     * @param catalogPattern null or the catalog name
1145     * @param schemaPattern the schema name of the primary table
1146     * @param tableName the name of the primary table
1147     * @return the result set
1148     * @throws SQLException if the connection is closed
1149     */
1150    @Override
1151    public ResultSet getExportedKeys(String catalogPattern,
1152            String schemaPattern, String tableName) throws SQLException {
1153        try {
1154            if (isDebugEnabled()) {
1155                debugCode("getExportedKeys("
1156                        +quote(catalogPattern)+", "
1157                        +quote(schemaPattern)+", "
1158                        +quote(tableName)+");");
1159            }
1160            checkClosed();
1161            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1162                    + "PKTABLE_CATALOG PKTABLE_CAT, "
1163                    + "PKTABLE_SCHEMA PKTABLE_SCHEM, "
1164                    + "PKTABLE_NAME PKTABLE_NAME, "
1165                    + "PKCOLUMN_NAME, "
1166                    + "FKTABLE_CATALOG FKTABLE_CAT, "
1167                    + "FKTABLE_SCHEMA FKTABLE_SCHEM, "
1168                    + "FKTABLE_NAME, "
1169                    + "FKCOLUMN_NAME, "
1170                    + "ORDINAL_POSITION KEY_SEQ, "
1171                    + "UPDATE_RULE, "
1172                    + "DELETE_RULE, "
1173                    + "FK_NAME, "
1174                    + "PK_NAME, "
1175                    + "DEFERRABILITY "
1176                    + "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
1177                    + "WHERE PKTABLE_CATALOG LIKE ? ESCAPE ? "
1178                    + "AND PKTABLE_SCHEMA LIKE ? ESCAPE ? "
1179                    + "AND PKTABLE_NAME = ? "
1180                    + "ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME, KEY_SEQ");
1181            prep.setString(1, getCatalogPattern(catalogPattern));
1182            prep.setString(2, "\\");
1183            prep.setString(3, getSchemaPattern(schemaPattern));
1184            prep.setString(4, "\\");
1185            prep.setString(5, tableName);
1186            return prep.executeQuery();
1187        } catch (Exception e) {
1188            throw logAndConvert(e);
1189        }
1190    }
1191 
1192    /**
1193     * Gets the list of foreign key columns that references a table, as well as
1194     * the list of primary key columns that are references by a table. The
1195     * result set is sorted by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME,
1196     * FK_NAME, KEY_SEQ.
1197     *
1198     * <ul>
1199     * <li>1 PKTABLE_CAT (String) primary catalog </li>
1200     * <li>2 PKTABLE_SCHEM (String) primary schema </li>
1201     * <li>3 PKTABLE_NAME (String) primary table </li>
1202     * <li>4 PKCOLUMN_NAME (String) primary column </li>
1203     * <li>5 FKTABLE_CAT (String) foreign catalog </li>
1204     * <li>6 FKTABLE_SCHEM (String) foreign schema </li>
1205     * <li>7 FKTABLE_NAME (String) foreign table </li>
1206     * <li>8 FKCOLUMN_NAME (String) foreign column </li>
1207     * <li>9 KEY_SEQ (short) sequence number (1,2,...) </li>
1208     * <li>10 UPDATE_RULE (short) action on update (see
1209     * DatabaseMetaData.importedKey...) </li>
1210     * <li>11 DELETE_RULE (short) action on delete (see
1211     * DatabaseMetaData.importedKey...) </li>
1212     * <li>12 FK_NAME (String) foreign key name </li>
1213     * <li>13 PK_NAME (String) primary key name </li>
1214     * <li>14 DEFERRABILITY (short) deferrable or not (always
1215     * importedKeyNotDeferrable) </li>
1216     * </ul>
1217     *
1218     * @param primaryCatalogPattern null or the catalog name
1219     * @param primarySchemaPattern the schema name of the primary table
1220     *          (optional)
1221     * @param primaryTable the name of the primary table (must be specified)
1222     * @param foreignCatalogPattern null or the catalog name
1223     * @param foreignSchemaPattern the schema name of the foreign table
1224     *          (optional)
1225     * @param foreignTable the name of the foreign table (must be specified)
1226     * @return the result set
1227     * @throws SQLException if the connection is closed
1228     */
1229    @Override
1230    public ResultSet getCrossReference(String primaryCatalogPattern,
1231            String primarySchemaPattern, String primaryTable, String foreignCatalogPattern,
1232            String foreignSchemaPattern, String foreignTable) throws SQLException {
1233        try {
1234            if (isDebugEnabled()) {
1235                debugCode("getCrossReference("
1236                        +quote(primaryCatalogPattern)+", "
1237                        +quote(primarySchemaPattern)+", "
1238                        +quote(primaryTable)+", "
1239                        +quote(foreignCatalogPattern)+", "
1240                        +quote(foreignSchemaPattern)+", "
1241                        +quote(foreignTable)+");");
1242            }
1243            checkClosed();
1244            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1245                    + "PKTABLE_CATALOG PKTABLE_CAT, "
1246                    + "PKTABLE_SCHEMA PKTABLE_SCHEM, "
1247                    + "PKTABLE_NAME PKTABLE_NAME, "
1248                    + "PKCOLUMN_NAME, "
1249                    + "FKTABLE_CATALOG FKTABLE_CAT, "
1250                    + "FKTABLE_SCHEMA FKTABLE_SCHEM, "
1251                    + "FKTABLE_NAME, "
1252                    + "FKCOLUMN_NAME, "
1253                    + "ORDINAL_POSITION KEY_SEQ, "
1254                    + "UPDATE_RULE, "
1255                    + "DELETE_RULE, "
1256                    + "FK_NAME, "
1257                    + "PK_NAME, "
1258                    + "DEFERRABILITY "
1259                    + "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
1260                    + "WHERE PKTABLE_CATALOG LIKE ? ESCAPE ? "
1261                    + "AND PKTABLE_SCHEMA LIKE ? ESCAPE ? "
1262                    + "AND PKTABLE_NAME = ? "
1263                    + "AND FKTABLE_CATALOG LIKE ? ESCAPE ? "
1264                    + "AND FKTABLE_SCHEMA LIKE ? ESCAPE ? "
1265                    + "AND FKTABLE_NAME = ? "
1266                    + "ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME, KEY_SEQ");
1267            prep.setString(1, getCatalogPattern(primaryCatalogPattern));
1268            prep.setString(2, "\\");
1269            prep.setString(3, getSchemaPattern(primarySchemaPattern));
1270            prep.setString(4, "\\");
1271            prep.setString(5, primaryTable);
1272            prep.setString(6, getCatalogPattern(foreignCatalogPattern));
1273            prep.setString(7, "\\");
1274            prep.setString(8, getSchemaPattern(foreignSchemaPattern));
1275            prep.setString(9, "\\");
1276            prep.setString(10, foreignTable);
1277            return prep.executeQuery();
1278        } catch (Exception e) {
1279            throw logAndConvert(e);
1280        }
1281    }
1282 
1283    /**
1284     * Gets the list of user-defined data types.
1285     * This call returns an empty result set.
1286     *
1287     * <ul>
1288     * <li>1 TYPE_CAT (String) catalog
1289     * </li><li>2 TYPE_SCHEM (String) schema
1290     * </li><li>3 TYPE_NAME (String) type name
1291     * </li><li>4 CLASS_NAME (String) Java class
1292     * </li><li>5 DATA_TYPE (short) SQL Type - see also java.sql.Types
1293     * </li><li>6 REMARKS (String) description
1294     * </li><li>7 BASE_TYPE (short) base type - see also java.sql.Types
1295     * </li></ul>
1296     *
1297     * @param catalog ignored
1298     * @param schemaPattern ignored
1299     * @param typeNamePattern ignored
1300     * @param types ignored
1301     * @return an empty result set
1302     * @throws SQLException if the connection is closed
1303     */
1304    @Override
1305    public ResultSet getUDTs(String catalog, String schemaPattern,
1306            String typeNamePattern, int[] types) throws SQLException {
1307        try {
1308            if (isDebugEnabled()) {
1309                debugCode("getUDTs("
1310                        +quote(catalog)+", "
1311                        +quote(schemaPattern)+", "
1312                        +quote(typeNamePattern)+", "
1313                        +quoteIntArray(types)+");");
1314            }
1315            checkClosed();
1316            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1317                    + "CAST(NULL AS VARCHAR) TYPE_CAT, "
1318                    + "CAST(NULL AS VARCHAR) TYPE_SCHEM, "
1319                    + "CAST(NULL AS VARCHAR) TYPE_NAME, "
1320                    + "CAST(NULL AS VARCHAR) CLASS_NAME, "
1321                    + "CAST(NULL AS SMALLINT) DATA_TYPE, "
1322                    + "CAST(NULL AS VARCHAR) REMARKS, "
1323                    + "CAST(NULL AS SMALLINT) BASE_TYPE "
1324                    + "FROM DUAL WHERE FALSE");
1325            return prep.executeQuery();
1326        } catch (Exception e) {
1327            throw logAndConvert(e);
1328        }
1329    }
1330 
1331    /**
1332     * Gets the list of data types. The result set is sorted by DATA_TYPE and
1333     * afterwards by how closely the data type maps to the corresponding JDBC
1334     * SQL type (best match first).
1335     *
1336     * <ul>
1337     * <li>1 TYPE_NAME (String) type name </li>
1338     * <li>2 DATA_TYPE (short) SQL data type - see also java.sql.Types </li>
1339     * <li>3 PRECISION (int) maximum precision </li>
1340     * <li>4 LITERAL_PREFIX (String) prefix used to quote a literal </li>
1341     * <li>5 LITERAL_SUFFIX (String) suffix used to quote a literal </li>
1342     * <li>6 CREATE_PARAMS (String) parameters used (may be null) </li>
1343     * <li>7 NULLABLE (short) typeNoNulls (NULL not allowed) or typeNullable
1344     * </li>
1345     * <li>8 CASE_SENSITIVE (boolean) case sensitive </li>
1346     * <li>9 SEARCHABLE (short) typeSearchable </li>
1347     * <li>10 UNSIGNED_ATTRIBUTE (boolean) unsigned </li>
1348     * <li>11 FIXED_PREC_SCALE (boolean) fixed precision </li>
1349     * <li>12 AUTO_INCREMENT (boolean) auto increment </li>
1350     * <li>13 LOCAL_TYPE_NAME (String) localized version of the data type </li>
1351     * <li>14 MINIMUM_SCALE (short) minimum scale </li>
1352     * <li>15 MAXIMUM_SCALE (short) maximum scale </li>
1353     * <li>16 SQL_DATA_TYPE (int) unused </li>
1354     * <li>17 SQL_DATETIME_SUB (int) unused </li>
1355     * <li>18 NUM_PREC_RADIX (int) 2 for binary, 10 for decimal </li>
1356     * </ul>
1357     *
1358     * @return the list of data types
1359     * @throws SQLException if the connection is closed
1360     */
1361    @Override
1362    public ResultSet getTypeInfo() throws SQLException {
1363        try {
1364            debugCodeCall("getTypeInfo");
1365            checkClosed();
1366            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
1367                    + "TYPE_NAME, "
1368                    + "DATA_TYPE, "
1369                    + "PRECISION, "
1370                    + "PREFIX LITERAL_PREFIX, "
1371                    + "SUFFIX LITERAL_SUFFIX, "
1372                    + "PARAMS CREATE_PARAMS, "
1373                    + "NULLABLE, "
1374                    + "CASE_SENSITIVE, "
1375                    + "SEARCHABLE, "
1376                    + "FALSE UNSIGNED_ATTRIBUTE, "
1377                    + "FALSE FIXED_PREC_SCALE, "
1378                    + "AUTO_INCREMENT, "
1379                    + "TYPE_NAME LOCAL_TYPE_NAME, "
1380                    + "MINIMUM_SCALE, "
1381                    + "MAXIMUM_SCALE, "
1382                    + "DATA_TYPE SQL_DATA_TYPE, "
1383                    + "ZERO() SQL_DATETIME_SUB, "
1384                    + "RADIX NUM_PREC_RADIX "
1385                    + "FROM INFORMATION_SCHEMA.TYPE_INFO "
1386                    + "ORDER BY DATA_TYPE, POS");
1387            ResultSet rs = prep.executeQuery();
1388            return rs;
1389        } catch (Exception e) {
1390            throw logAndConvert(e);
1391        }
1392    }
1393 
1394    /**
1395     * Checks if this database store data in local files.
1396     *
1397     * @return true
1398     */
1399    @Override
1400    public boolean usesLocalFiles() {
1401        debugCodeCall("usesLocalFiles");
1402        return true;
1403    }
1404 
1405    /**
1406     * Checks if this database use one file per table.
1407     *
1408     * @return false
1409     */
1410    @Override
1411    public boolean usesLocalFilePerTable() {
1412        debugCodeCall("usesLocalFilePerTable");
1413        return false;
1414    }
1415 
1416    /**
1417     * Returns the string used to quote identifiers.
1418     *
1419     * @return a double quote
1420     */
1421    @Override
1422    public String getIdentifierQuoteString() {
1423        debugCodeCall("getIdentifierQuoteString");
1424        return "\"";
1425    }
1426 
1427    /**
1428     * Gets the comma-separated list of all SQL keywords that are not supported
1429     * as table/column/index name, in addition to the SQL-92 keywords. The list
1430     * returned is:
1431     * <pre>
1432     * LIMIT,MINUS,ROWNUM,SYSDATE,SYSTIME,SYSTIMESTAMP,TODAY
1433     * </pre>
1434     * The complete list of keywords (including SQL-92 keywords) is:
1435     * <pre>
1436     * CROSS, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, DISTINCT,
1437     * EXCEPT, EXISTS, FALSE, FOR, FROM, FULL, GROUP, HAVING, INNER,
1438     * INTERSECT, IS, JOIN, LIKE, LIMIT, MINUS, NATURAL, NOT, NULL, ON,
1439     * ORDER, PRIMARY, ROWNUM, SELECT, SYSDATE, SYSTIME, SYSTIMESTAMP,
1440     * TODAY, TRUE, UNION, UNIQUE, WHERE
1441     * </pre>
1442     *
1443     * @return a list of additional the keywords
1444     */
1445    @Override
1446    public String getSQLKeywords() {
1447        debugCodeCall("getSQLKeywords");
1448        return "LIMIT,MINUS,ROWNUM,SYSDATE,SYSTIME,SYSTIMESTAMP,TODAY";
1449    }
1450 
1451    /**
1452     * Returns the list of numeric functions supported by this database.
1453     *
1454     * @return the list
1455     */
1456    @Override
1457    public String getNumericFunctions() throws SQLException {
1458        debugCodeCall("getNumericFunctions");
1459        return getFunctions("Functions (Numeric)");
1460    }
1461 
1462    /**
1463     * Returns the list of string functions supported by this database.
1464     *
1465     * @return the list
1466     */
1467    @Override
1468    public String getStringFunctions() throws SQLException {
1469        debugCodeCall("getStringFunctions");
1470        return getFunctions("Functions (String)");
1471    }
1472 
1473    /**
1474     * Returns the list of system functions supported by this database.
1475     *
1476     * @return the list
1477     */
1478    @Override
1479    public String getSystemFunctions() throws SQLException {
1480        debugCodeCall("getSystemFunctions");
1481        return getFunctions("Functions (System)");
1482    }
1483 
1484    /**
1485     * Returns the list of date and time functions supported by this database.
1486     *
1487     * @return the list
1488     */
1489    @Override
1490    public String getTimeDateFunctions() throws SQLException {
1491        debugCodeCall("getTimeDateFunctions");
1492        return getFunctions("Functions (Time and Date)");
1493    }
1494 
1495    private String getFunctions(String section) throws SQLException {
1496        try {
1497            checkClosed();
1498            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT TOPIC "
1499                    + "FROM INFORMATION_SCHEMA.HELP WHERE SECTION = ?");
1500            prep.setString(1, section);
1501            ResultSet rs = prep.executeQuery();
1502            StatementBuilder buff = new StatementBuilder();
1503            while (rs.next()) {
1504                String s = rs.getString(1).trim();
1505                String[] array = StringUtils.arraySplit(s, ',', true);
1506                for (String a : array) {
1507                    buff.appendExceptFirst(",");
1508                    String f = a.trim();
1509                    if (f.indexOf(' ') >= 0) {
1510                        // remove 'Function' from 'INSERT Function'
1511                        f = f.substring(0, f.indexOf(' ')).trim();
1512                    }
1513                    buff.append(f);
1514                }
1515            }
1516            rs.close();
1517            prep.close();
1518            return buff.toString();
1519        } catch (Exception e) {
1520            throw logAndConvert(e);
1521        }
1522    }
1523 
1524    /**
1525     * Returns the default escape character for DatabaseMetaData search
1526     * patterns.
1527     *
1528     * @return the default escape character (always '\', independent on the
1529     *         mode)
1530     */
1531    @Override
1532    public String getSearchStringEscape() {
1533        debugCodeCall("getSearchStringEscape");
1534        return "\\";
1535    }
1536 
1537    /**
1538     * Returns the characters that are allowed for identifiers in addiction to
1539     * A-Z, a-z, 0-9 and '_'.
1540     *
1541     * @return an empty String ("")
1542     */
1543    @Override
1544    public String getExtraNameCharacters() {
1545        debugCodeCall("getExtraNameCharacters");
1546        return "";
1547    }
1548 
1549    /**
1550     * Returns whether alter table with add column is supported.
1551     * @return true
1552     */
1553    @Override
1554    public boolean supportsAlterTableWithAddColumn() {
1555        debugCodeCall("supportsAlterTableWithAddColumn");
1556        return true;
1557    }
1558 
1559    /**
1560     * Returns whether alter table with drop column is supported.
1561     *
1562     * @return true
1563     */
1564    @Override
1565    public boolean supportsAlterTableWithDropColumn() {
1566        debugCodeCall("supportsAlterTableWithDropColumn");
1567        return true;
1568    }
1569 
1570    /**
1571     * Returns whether column aliasing is supported.
1572     *
1573     * @return true
1574     */
1575    @Override
1576    public boolean supportsColumnAliasing() {
1577        debugCodeCall("supportsColumnAliasing");
1578        return true;
1579    }
1580 
1581    /**
1582     * Returns whether NULL+1 is NULL or not.
1583     *
1584     * @return true
1585     */
1586    @Override
1587    public boolean nullPlusNonNullIsNull() {
1588        debugCodeCall("nullPlusNonNullIsNull");
1589        return true;
1590    }
1591 
1592    /**
1593     * Returns whether CONVERT is supported.
1594     *
1595     * @return true
1596     */
1597    @Override
1598    public boolean supportsConvert() {
1599        debugCodeCall("supportsConvert");
1600        return true;
1601    }
1602 
1603    /**
1604     * Returns whether CONVERT is supported for one datatype to another.
1605     *
1606     * @param fromType the source SQL type
1607     * @param toType the target SQL type
1608     * @return true
1609     */
1610    @Override
1611    public boolean supportsConvert(int fromType, int toType) {
1612        if (isDebugEnabled()) {
1613            debugCode("supportsConvert("+fromType+", "+fromType+");");
1614        }
1615        return true;
1616    }
1617 
1618    /**
1619     * Returns whether table correlation names (table alias) are supported.
1620     *
1621     * @return true
1622     */
1623    @Override
1624    public boolean supportsTableCorrelationNames() {
1625        debugCodeCall("supportsTableCorrelationNames");
1626        return true;
1627    }
1628 
1629    /**
1630     * Returns whether table correlation names (table alias) are restricted to
1631     * be different than table names.
1632     *
1633     * @return false
1634     */
1635    @Override
1636    public boolean supportsDifferentTableCorrelationNames() {
1637        debugCodeCall("supportsDifferentTableCorrelationNames");
1638        return false;
1639    }
1640 
1641    /**
1642     * Returns whether expression in ORDER BY are supported.
1643     *
1644     * @return true
1645     */
1646    @Override
1647    public boolean supportsExpressionsInOrderBy() {
1648        debugCodeCall("supportsExpressionsInOrderBy");
1649        return true;
1650    }
1651 
1652    /**
1653     * Returns whether ORDER BY is supported if the column is not in the SELECT
1654     * list.
1655     *
1656     * @return true
1657     */
1658    @Override
1659    public boolean supportsOrderByUnrelated() {
1660        debugCodeCall("supportsOrderByUnrelated");
1661        return true;
1662    }
1663 
1664    /**
1665     * Returns whether GROUP BY is supported.
1666     *
1667     * @return true
1668     */
1669    @Override
1670    public boolean supportsGroupBy() {
1671        debugCodeCall("supportsGroupBy");
1672        return true;
1673    }
1674 
1675    /**
1676     * Returns whether GROUP BY is supported if the column is not in the SELECT
1677     * list.
1678     *
1679     * @return true
1680     */
1681    @Override
1682    public boolean supportsGroupByUnrelated() {
1683        debugCodeCall("supportsGroupByUnrelated");
1684        return true;
1685    }
1686 
1687    /**
1688     * Checks whether a GROUP BY clause can use columns that are not in the
1689     * SELECT clause, provided that it specifies all the columns in the SELECT
1690     * clause.
1691     *
1692     * @return true
1693     */
1694    @Override
1695    public boolean supportsGroupByBeyondSelect() {
1696        debugCodeCall("supportsGroupByBeyondSelect");
1697        return true;
1698    }
1699 
1700    /**
1701     * Returns whether LIKE... ESCAPE is supported.
1702     *
1703     * @return true
1704     */
1705    @Override
1706    public boolean supportsLikeEscapeClause() {
1707        debugCodeCall("supportsLikeEscapeClause");
1708        return true;
1709    }
1710 
1711    /**
1712     * Returns whether multiple result sets are supported.
1713     *
1714     * @return false
1715     */
1716    @Override
1717    public boolean supportsMultipleResultSets() {
1718        debugCodeCall("supportsMultipleResultSets");
1719        return false;
1720    }
1721 
1722    /**
1723     * Returns whether multiple transactions (on different connections) are
1724     * supported.
1725     *
1726     * @return true
1727     */
1728    @Override
1729    public boolean supportsMultipleTransactions() {
1730        debugCodeCall("supportsMultipleTransactions");
1731        return true;
1732    }
1733 
1734    /**
1735     * Returns whether columns with NOT NULL are supported.
1736     *
1737     * @return true
1738     */
1739    @Override
1740    public boolean supportsNonNullableColumns() {
1741        debugCodeCall("supportsNonNullableColumns");
1742        return true;
1743    }
1744 
1745    /**
1746     * Returns whether ODBC Minimum SQL grammar is supported.
1747     *
1748     * @return true
1749     */
1750    @Override
1751    public boolean supportsMinimumSQLGrammar() {
1752        debugCodeCall("supportsMinimumSQLGrammar");
1753        return true;
1754    }
1755 
1756    /**
1757     * Returns whether ODBC Core SQL grammar is supported.
1758     *
1759     * @return true
1760     */
1761    @Override
1762    public boolean supportsCoreSQLGrammar() {
1763        debugCodeCall("supportsCoreSQLGrammar");
1764        return true;
1765    }
1766 
1767    /**
1768     * Returns whether ODBC Extended SQL grammar is supported.
1769     *
1770     * @return false
1771     */
1772    @Override
1773    public boolean supportsExtendedSQLGrammar() {
1774        debugCodeCall("supportsExtendedSQLGrammar");
1775        return false;
1776    }
1777 
1778    /**
1779     * Returns whether SQL-92 entry level grammar is supported.
1780     *
1781     * @return true
1782     */
1783    @Override
1784    public boolean supportsANSI92EntryLevelSQL() {
1785        debugCodeCall("supportsANSI92EntryLevelSQL");
1786        return true;
1787    }
1788 
1789    /**
1790     * Returns whether SQL-92 intermediate level grammar is supported.
1791     *
1792     * @return false
1793     */
1794    @Override
1795    public boolean supportsANSI92IntermediateSQL() {
1796        debugCodeCall("supportsANSI92IntermediateSQL");
1797        return false;
1798    }
1799 
1800    /**
1801     * Returns whether SQL-92 full level grammar is supported.
1802     *
1803     * @return false
1804     */
1805    @Override
1806    public boolean supportsANSI92FullSQL() {
1807        debugCodeCall("supportsANSI92FullSQL");
1808        return false;
1809    }
1810 
1811    /**
1812     * Returns whether referential integrity is supported.
1813     *
1814     * @return true
1815     */
1816    @Override
1817    public boolean supportsIntegrityEnhancementFacility() {
1818        debugCodeCall("supportsIntegrityEnhancementFacility");
1819        return true;
1820    }
1821 
1822    /**
1823     * Returns whether outer joins are supported.
1824     *
1825     * @return true
1826     */
1827    @Override
1828    public boolean supportsOuterJoins() {
1829        debugCodeCall("supportsOuterJoins");
1830        return true;
1831    }
1832 
1833    /**
1834     * Returns whether full outer joins are supported.
1835     *
1836     * @return false
1837     */
1838    @Override
1839    public boolean supportsFullOuterJoins() {
1840        debugCodeCall("supportsFullOuterJoins");
1841        return false;
1842    }
1843 
1844    /**
1845     * Returns whether limited outer joins are supported.
1846     *
1847     * @return true
1848     */
1849    @Override
1850    public boolean supportsLimitedOuterJoins() {
1851        debugCodeCall("supportsLimitedOuterJoins");
1852        return true;
1853    }
1854 
1855    /**
1856     * Returns the term for "schema".
1857     *
1858     * @return "schema"
1859     */
1860    @Override
1861    public String getSchemaTerm() {
1862        debugCodeCall("getSchemaTerm");
1863        return "schema";
1864    }
1865 
1866    /**
1867     * Returns the term for "procedure".
1868     *
1869     * @return "procedure"
1870     */
1871    @Override
1872    public String getProcedureTerm() {
1873        debugCodeCall("getProcedureTerm");
1874        return "procedure";
1875    }
1876 
1877    /**
1878     * Returns the term for "catalog".
1879     *
1880     * @return "catalog"
1881     */
1882    @Override
1883    public String getCatalogTerm() {
1884        debugCodeCall("getCatalogTerm");
1885        return "catalog";
1886    }
1887 
1888    /**
1889     * Returns whether the catalog is at the beginning.
1890     *
1891     * @return true
1892     */
1893    @Override
1894    public boolean isCatalogAtStart() {
1895        debugCodeCall("isCatalogAtStart");
1896        return true;
1897    }
1898 
1899    /**
1900     * Returns the catalog separator.
1901     *
1902     * @return "."
1903     */
1904    @Override
1905    public String getCatalogSeparator() {
1906        debugCodeCall("getCatalogSeparator");
1907        return ".";
1908    }
1909 
1910    /**
1911     * Returns whether the schema name in INSERT, UPDATE, DELETE is supported.
1912     *
1913     * @return true
1914     */
1915    @Override
1916    public boolean supportsSchemasInDataManipulation() {
1917        debugCodeCall("supportsSchemasInDataManipulation");
1918        return true;
1919    }
1920 
1921    /**
1922     * Returns whether the schema name in procedure calls is supported.
1923     *
1924     * @return true
1925     */
1926    @Override
1927    public boolean supportsSchemasInProcedureCalls() {
1928        debugCodeCall("supportsSchemasInProcedureCalls");
1929        return true;
1930    }
1931 
1932    /**
1933     * Returns whether the schema name in CREATE TABLE is supported.
1934     *
1935     * @return true
1936     */
1937    @Override
1938    public boolean supportsSchemasInTableDefinitions() {
1939        debugCodeCall("supportsSchemasInTableDefinitions");
1940        return true;
1941    }
1942 
1943    /**
1944     * Returns whether the schema name in CREATE INDEX is supported.
1945     *
1946     * @return true
1947     */
1948    @Override
1949    public boolean supportsSchemasInIndexDefinitions() {
1950        debugCodeCall("supportsSchemasInIndexDefinitions");
1951        return true;
1952    }
1953 
1954    /**
1955     * Returns whether the schema name in GRANT is supported.
1956     *
1957     * @return true
1958     */
1959    @Override
1960    public boolean supportsSchemasInPrivilegeDefinitions() {
1961        debugCodeCall("supportsSchemasInPrivilegeDefinitions");
1962        return true;
1963    }
1964 
1965    /**
1966     * Returns whether the catalog name in INSERT, UPDATE, DELETE is supported.
1967     *
1968     * @return true
1969     */
1970    @Override
1971    public boolean supportsCatalogsInDataManipulation() {
1972        debugCodeCall("supportsCatalogsInDataManipulation");
1973        return true;
1974    }
1975 
1976    /**
1977     * Returns whether the catalog name in procedure calls is supported.
1978     *
1979     * @return false
1980     */
1981    @Override
1982    public boolean supportsCatalogsInProcedureCalls() {
1983        debugCodeCall("supportsCatalogsInProcedureCalls");
1984        return false;
1985    }
1986 
1987    /**
1988     * Returns whether the catalog name in CREATE TABLE is supported.
1989     *
1990     * @return true
1991     */
1992    @Override
1993    public boolean supportsCatalogsInTableDefinitions() {
1994        debugCodeCall("supportsCatalogsInTableDefinitions");
1995        return true;
1996    }
1997 
1998    /**
1999     * Returns whether the catalog name in CREATE INDEX is supported.
2000     *
2001     * @return true
2002     */
2003    @Override
2004    public boolean supportsCatalogsInIndexDefinitions() {
2005        debugCodeCall("supportsCatalogsInIndexDefinitions");
2006        return true;
2007    }
2008 
2009    /**
2010     * Returns whether the catalog name in GRANT is supported.
2011     *
2012     * @return true
2013     */
2014    @Override
2015    public boolean supportsCatalogsInPrivilegeDefinitions() {
2016        debugCodeCall("supportsCatalogsInPrivilegeDefinitions");
2017        return true;
2018    }
2019 
2020    /**
2021     * Returns whether positioned deletes are supported.
2022     *
2023     * @return true
2024     */
2025    @Override
2026    public boolean supportsPositionedDelete() {
2027        debugCodeCall("supportsPositionedDelete");
2028        return true;
2029    }
2030 
2031    /**
2032     * Returns whether positioned updates are supported.
2033     *
2034     * @return true
2035     */
2036    @Override
2037    public boolean supportsPositionedUpdate() {
2038        debugCodeCall("supportsPositionedUpdate");
2039        return true;
2040    }
2041 
2042    /**
2043     * Returns whether SELECT ... FOR UPDATE is supported.
2044     *
2045     * @return true
2046     */
2047    @Override
2048    public boolean supportsSelectForUpdate() {
2049        debugCodeCall("supportsSelectForUpdate");
2050        return true;
2051    }
2052 
2053    /**
2054     * Returns whether stored procedures are supported.
2055     *
2056     * @return false
2057     */
2058    @Override
2059    public boolean supportsStoredProcedures() {
2060        debugCodeCall("supportsStoredProcedures");
2061        return false;
2062    }
2063 
2064    /**
2065     * Returns whether subqueries (SELECT) in comparisons are supported.
2066     *
2067     * @return true
2068     */
2069    @Override
2070    public boolean supportsSubqueriesInComparisons() {
2071        debugCodeCall("supportsSubqueriesInComparisons");
2072        return true;
2073    }
2074 
2075    /**
2076     * Returns whether SELECT in EXISTS is supported.
2077     *
2078     * @return true
2079     */
2080    @Override
2081    public boolean supportsSubqueriesInExists() {
2082        debugCodeCall("supportsSubqueriesInExists");
2083        return true;
2084    }
2085 
2086    /**
2087     * Returns whether IN(SELECT...) is supported.
2088     *
2089     * @return true
2090     */
2091    @Override
2092    public boolean supportsSubqueriesInIns() {
2093        debugCodeCall("supportsSubqueriesInIns");
2094        return true;
2095    }
2096 
2097    /**
2098     * Returns whether subqueries in quantified expression are supported.
2099     *
2100     * @return true
2101     */
2102    @Override
2103    public boolean supportsSubqueriesInQuantifieds() {
2104        debugCodeCall("supportsSubqueriesInQuantifieds");
2105        return true;
2106    }
2107 
2108    /**
2109     * Returns whether correlated subqueries are supported.
2110     *
2111     * @return true
2112     */
2113    @Override
2114    public boolean supportsCorrelatedSubqueries() {
2115        debugCodeCall("supportsCorrelatedSubqueries");
2116        return true;
2117    }
2118 
2119    /**
2120     * Returns whether UNION SELECT is supported.
2121     *
2122     * @return true
2123     */
2124    @Override
2125    public boolean supportsUnion() {
2126        debugCodeCall("supportsUnion");
2127        return true;
2128    }
2129 
2130    /**
2131     * Returns whether UNION ALL SELECT is supported.
2132     *
2133     * @return true
2134     */
2135    @Override
2136    public boolean supportsUnionAll() {
2137        debugCodeCall("supportsUnionAll");
2138        return true;
2139    }
2140 
2141    /**
2142     * Returns whether open result sets across commits are supported.
2143     *
2144     * @return false
2145     */
2146    @Override
2147    public boolean supportsOpenCursorsAcrossCommit() {
2148        debugCodeCall("supportsOpenCursorsAcrossCommit");
2149        return false;
2150    }
2151 
2152    /**
2153     * Returns whether open result sets across rollback are supported.
2154     *
2155     * @return false
2156     */
2157    @Override
2158    public boolean supportsOpenCursorsAcrossRollback() {
2159        debugCodeCall("supportsOpenCursorsAcrossRollback");
2160        return false;
2161    }
2162 
2163    /**
2164     * Returns whether open statements across commit are supported.
2165     *
2166     * @return true
2167     */
2168    @Override
2169    public boolean supportsOpenStatementsAcrossCommit() {
2170        debugCodeCall("supportsOpenStatementsAcrossCommit");
2171        return true;
2172    }
2173 
2174    /**
2175     * Returns whether open statements across rollback are supported.
2176     *
2177     * @return true
2178     */
2179    @Override
2180    public boolean supportsOpenStatementsAcrossRollback() {
2181        debugCodeCall("supportsOpenStatementsAcrossRollback");
2182        return true;
2183    }
2184 
2185    /**
2186     * Returns whether transactions are supported.
2187     *
2188     * @return true
2189     */
2190    @Override
2191    public boolean supportsTransactions() {
2192        debugCodeCall("supportsTransactions");
2193        return true;
2194    }
2195 
2196    /**
2197     * Returns whether a specific transaction isolation level is supported.
2198     *
2199     * @param level the transaction isolation level (Connection.TRANSACTION_*)
2200     * @return true
2201     */
2202    @Override
2203    public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
2204        debugCodeCall("supportsTransactionIsolationLevel");
2205        if (level == Connection.TRANSACTION_READ_UNCOMMITTED) {
2206            // currently the combination of LOCK_MODE=0 and MULTI_THREADED
2207            // is not supported, also see code in Database#setLockMode(int)
2208            PreparedStatement prep = conn.prepareAutoCloseStatement(
2209                    "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?");
2210            prep.setString(1, "MULTI_THREADED");
2211            ResultSet rs = prep.executeQuery();
2212            if (rs.next() && rs.getString(1).equals("1")) {
2213                return false;
2214            }
2215        }
2216        return true;
2217    }
2218 
2219    /**
2220     * Returns whether data manipulation and CREATE/DROP is supported in
2221     * transactions.
2222     *
2223     * @return false
2224     */
2225    @Override
2226    public boolean supportsDataDefinitionAndDataManipulationTransactions() {
2227        debugCodeCall("supportsDataDefinitionAndDataManipulationTransactions");
2228        return false;
2229    }
2230 
2231    /**
2232     * Returns whether only data manipulations are supported in transactions.
2233     *
2234     * @return true
2235     */
2236    @Override
2237    public boolean supportsDataManipulationTransactionsOnly() {
2238        debugCodeCall("supportsDataManipulationTransactionsOnly");
2239        return true;
2240    }
2241 
2242    /**
2243     * Returns whether CREATE/DROP commit an open transaction.
2244     *
2245     * @return true
2246     */
2247    @Override
2248    public boolean dataDefinitionCausesTransactionCommit() {
2249        debugCodeCall("dataDefinitionCausesTransactionCommit");
2250        return true;
2251    }
2252 
2253    /**
2254     * Returns whether CREATE/DROP do not affect transactions.
2255     *
2256     * @return false
2257     */
2258    @Override
2259    public boolean dataDefinitionIgnoredInTransactions() {
2260        debugCodeCall("dataDefinitionIgnoredInTransactions");
2261        return false;
2262    }
2263 
2264    /**
2265     * Returns whether a specific result set type is supported.
2266     * ResultSet.TYPE_SCROLL_SENSITIVE is not supported.
2267     *
2268     * @param type the result set type
2269     * @return true for all types except ResultSet.TYPE_FORWARD_ONLY
2270     */
2271    @Override
2272    public boolean supportsResultSetType(int type) {
2273        debugCodeCall("supportsResultSetType", type);
2274        return type != ResultSet.TYPE_SCROLL_SENSITIVE;
2275    }
2276 
2277    /**
2278     * Returns whether a specific result set concurrency is supported.
2279     * ResultSet.TYPE_SCROLL_SENSITIVE is not supported.
2280     *
2281     * @param type the result set type
2282     * @param concurrency the result set concurrency
2283     * @return true if the type is not ResultSet.TYPE_SCROLL_SENSITIVE
2284     */
2285    @Override
2286    public boolean supportsResultSetConcurrency(int type, int concurrency) {
2287        if (isDebugEnabled()) {
2288            debugCode("supportsResultSetConcurrency("+type+", "+concurrency+");");
2289        }
2290        return type != ResultSet.TYPE_SCROLL_SENSITIVE;
2291    }
2292 
2293    /**
2294     * Returns whether own updates are visible.
2295     *
2296     * @param type the result set type
2297     * @return true
2298     */
2299    @Override
2300    public boolean ownUpdatesAreVisible(int type) {
2301        debugCodeCall("ownUpdatesAreVisible", type);
2302        return true;
2303    }
2304 
2305    /**
2306     * Returns whether own deletes are visible.
2307     *
2308     * @param type the result set type
2309     * @return false
2310     */
2311    @Override
2312    public boolean ownDeletesAreVisible(int type) {
2313        debugCodeCall("ownDeletesAreVisible", type);
2314        return false;
2315    }
2316 
2317    /**
2318     * Returns whether own inserts are visible.
2319     *
2320     * @param type the result set type
2321     * @return false
2322     */
2323    @Override
2324    public boolean ownInsertsAreVisible(int type) {
2325        debugCodeCall("ownInsertsAreVisible", type);
2326        return false;
2327    }
2328 
2329    /**
2330     * Returns whether other updates are visible.
2331     *
2332     * @param type the result set type
2333     * @return false
2334     */
2335    @Override
2336    public boolean othersUpdatesAreVisible(int type) {
2337        debugCodeCall("othersUpdatesAreVisible", type);
2338        return false;
2339    }
2340 
2341    /**
2342     * Returns whether other deletes are visible.
2343     *
2344     * @param type the result set type
2345     * @return false
2346     */
2347    @Override
2348    public boolean othersDeletesAreVisible(int type) {
2349        debugCodeCall("othersDeletesAreVisible", type);
2350        return false;
2351    }
2352 
2353    /**
2354     * Returns whether other inserts are visible.
2355     *
2356     * @param type the result set type
2357     * @return false
2358     */
2359    @Override
2360    public boolean othersInsertsAreVisible(int type) {
2361        debugCodeCall("othersInsertsAreVisible", type);
2362        return false;
2363    }
2364 
2365    /**
2366     * Returns whether updates are detected.
2367     *
2368     * @param type the result set type
2369     * @return false
2370     */
2371    @Override
2372    public boolean updatesAreDetected(int type) {
2373        debugCodeCall("updatesAreDetected", type);
2374        return false;
2375    }
2376 
2377    /**
2378     * Returns whether deletes are detected.
2379     *
2380     * @param type the result set type
2381     * @return false
2382     */
2383    @Override
2384    public boolean deletesAreDetected(int type) {
2385        debugCodeCall("deletesAreDetected", type);
2386        return false;
2387    }
2388 
2389    /**
2390     * Returns whether inserts are detected.
2391     *
2392     * @param type the result set type
2393     * @return false
2394     */
2395    @Override
2396    public boolean insertsAreDetected(int type) {
2397        debugCodeCall("insertsAreDetected", type);
2398        return false;
2399    }
2400 
2401    /**
2402     * Returns whether batch updates are supported.
2403     *
2404     * @return true
2405     */
2406    @Override
2407    public boolean supportsBatchUpdates() {
2408        debugCodeCall("supportsBatchUpdates");
2409        return true;
2410    }
2411 
2412    /**
2413     * Returns whether the maximum row size includes blobs.
2414     *
2415     * @return false
2416     */
2417    @Override
2418    public boolean doesMaxRowSizeIncludeBlobs() {
2419        debugCodeCall("doesMaxRowSizeIncludeBlobs");
2420        return false;
2421    }
2422 
2423    /**
2424     * Returns the default transaction isolation level.
2425     *
2426     * @return Connection.TRANSACTION_READ_COMMITTED
2427     */
2428    @Override
2429    public int getDefaultTransactionIsolation() {
2430        debugCodeCall("getDefaultTransactionIsolation");
2431        return Connection.TRANSACTION_READ_COMMITTED;
2432    }
2433 
2434    /**
2435     * Checks if for CREATE TABLE Test(ID INT), getTables returns Test as the
2436     * table name.
2437     *
2438     * @return false
2439     */
2440    @Override
2441    public boolean supportsMixedCaseIdentifiers() {
2442        debugCodeCall("supportsMixedCaseIdentifiers");
2443        return false;
2444    }
2445 
2446    /**
2447     * Checks if a table created with CREATE TABLE "Test"(ID INT) is a different
2448     * table than a table created with CREATE TABLE TEST(ID INT).
2449     *
2450     * @return true usually, and false in MySQL mode
2451     */
2452    @Override
2453    public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
2454        debugCodeCall("supportsMixedCaseQuotedIdentifiers");
2455        String m = getMode();
2456        if (m.equals("MySQL")) {
2457            return false;
2458        }
2459        return true;
2460    }
2461 
2462    /**
2463     * Checks if for CREATE TABLE Test(ID INT), getTables returns TEST as the
2464     * table name.
2465     *
2466     * @return true usually, and false in MySQL mode
2467     */
2468    @Override
2469    public boolean storesUpperCaseIdentifiers() throws SQLException {
2470        debugCodeCall("storesUpperCaseIdentifiers");
2471        String m = getMode();
2472        if (m.equals("MySQL")) {
2473            return false;
2474        }
2475        return true;
2476    }
2477 
2478    /**
2479     * Checks if for CREATE TABLE Test(ID INT), getTables returns test as the
2480     * table name.
2481     *
2482     * @return false usually, and true in MySQL mode
2483     */
2484    @Override
2485    public boolean storesLowerCaseIdentifiers() throws SQLException {
2486        debugCodeCall("storesLowerCaseIdentifiers");
2487        String m = getMode();
2488        if (m.equals("MySQL")) {
2489            return true;
2490        }
2491        return false;
2492    }
2493 
2494    /**
2495     * Checks if for CREATE TABLE Test(ID INT), getTables returns Test as the
2496     * table name.
2497     *
2498     * @return false
2499     */
2500    @Override
2501    public boolean storesMixedCaseIdentifiers() {
2502        debugCodeCall("storesMixedCaseIdentifiers");
2503        return false;
2504    }
2505 
2506    /**
2507     * Checks if for CREATE TABLE "Test"(ID INT), getTables returns TEST as the
2508     * table name.
2509     *
2510     * @return false usually, and true in MySQL mode
2511     */
2512    @Override
2513    public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
2514        debugCodeCall("storesUpperCaseQuotedIdentifiers");
2515        String m = getMode();
2516        if (m.equals("MySQL")) {
2517            return true;
2518        }
2519        return false;
2520    }
2521 
2522    /**
2523     * Checks if for CREATE TABLE "Test"(ID INT), getTables returns test as the
2524     * table name.
2525     *
2526     * @return false usually, and true in MySQL mode
2527     */
2528    @Override
2529    public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
2530        debugCodeCall("storesLowerCaseQuotedIdentifiers");
2531        String m = getMode();
2532        if (m.equals("MySQL")) {
2533            return true;
2534        }
2535        return false;
2536    }
2537 
2538    /**
2539     * Checks if for CREATE TABLE "Test"(ID INT), getTables returns Test as the
2540     * table name.
2541     *
2542     * @return true usually, and false in MySQL mode
2543     */
2544    @Override
2545    public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
2546        debugCodeCall("storesMixedCaseQuotedIdentifiers");
2547        String m = getMode();
2548        if (m.equals("MySQL")) {
2549            return false;
2550        }
2551        return true;
2552    }
2553 
2554    /**
2555     * Returns the maximum length for hex values (characters).
2556     *
2557     * @return 0 for limit is unknown
2558     */
2559    @Override
2560    public int getMaxBinaryLiteralLength() {
2561        debugCodeCall("getMaxBinaryLiteralLength");
2562        return 0;
2563    }
2564 
2565    /**
2566     * Returns the maximum length for literals.
2567     *
2568     * @return 0 for limit is unknown
2569     */
2570    @Override
2571    public int getMaxCharLiteralLength() {
2572        debugCodeCall("getMaxCharLiteralLength");
2573        return 0;
2574    }
2575 
2576    /**
2577     * Returns the maximum length for column names.
2578     *
2579     * @return 0 for limit is unknown
2580     */
2581    @Override
2582    public int getMaxColumnNameLength() {
2583        debugCodeCall("getMaxColumnNameLength");
2584        return 0;
2585    }
2586 
2587    /**
2588     * Returns the maximum number of columns in GROUP BY.
2589     *
2590     * @return 0 for limit is unknown
2591     */
2592    @Override
2593    public int getMaxColumnsInGroupBy() {
2594        debugCodeCall("getMaxColumnsInGroupBy");
2595        return 0;
2596    }
2597 
2598    /**
2599     * Returns the maximum number of columns in CREATE INDEX.
2600     *
2601     * @return 0 for limit is unknown
2602     */
2603    @Override
2604    public int getMaxColumnsInIndex() {
2605        debugCodeCall("getMaxColumnsInIndex");
2606        return 0;
2607    }
2608 
2609    /**
2610     * Returns the maximum number of columns in ORDER BY.
2611     *
2612     * @return 0 for limit is unknown
2613     */
2614    @Override
2615    public int getMaxColumnsInOrderBy() {
2616        debugCodeCall("getMaxColumnsInOrderBy");
2617        return 0;
2618    }
2619 
2620    /**
2621     * Returns the maximum number of columns in SELECT.
2622     *
2623     * @return 0 for limit is unknown
2624     */
2625    @Override
2626    public int getMaxColumnsInSelect() {
2627        debugCodeCall("getMaxColumnsInSelect");
2628        return 0;
2629    }
2630 
2631    /**
2632     * Returns the maximum number of columns in CREATE TABLE.
2633     *
2634     * @return 0 for limit is unknown
2635     */
2636    @Override
2637    public int getMaxColumnsInTable() {
2638        debugCodeCall("getMaxColumnsInTable");
2639        return 0;
2640    }
2641 
2642    /**
2643     * Returns the maximum number of open connection.
2644     *
2645     * @return 0 for limit is unknown
2646     */
2647    @Override
2648    public int getMaxConnections() {
2649        debugCodeCall("getMaxConnections");
2650        return 0;
2651    }
2652 
2653    /**
2654     * Returns the maximum length for a cursor name.
2655     *
2656     * @return 0 for limit is unknown
2657     */
2658    @Override
2659    public int getMaxCursorNameLength() {
2660        debugCodeCall("getMaxCursorNameLength");
2661        return 0;
2662    }
2663 
2664    /**
2665     * Returns the maximum length for an index (in bytes).
2666     *
2667     * @return 0 for limit is unknown
2668     */
2669    @Override
2670    public int getMaxIndexLength() {
2671        debugCodeCall("getMaxIndexLength");
2672        return 0;
2673    }
2674 
2675    /**
2676     * Returns the maximum length for a schema name.
2677     *
2678     * @return 0 for limit is unknown
2679     */
2680    @Override
2681    public int getMaxSchemaNameLength() {
2682        debugCodeCall("getMaxSchemaNameLength");
2683        return 0;
2684    }
2685 
2686    /**
2687     * Returns the maximum length for a procedure name.
2688     *
2689     * @return 0 for limit is unknown
2690     */
2691    @Override
2692    public int getMaxProcedureNameLength() {
2693        debugCodeCall("getMaxProcedureNameLength");
2694        return 0;
2695    }
2696 
2697    /**
2698     * Returns the maximum length for a catalog name.
2699     *
2700     * @return 0 for limit is unknown
2701     */
2702    @Override
2703    public int getMaxCatalogNameLength() {
2704        debugCodeCall("getMaxCatalogNameLength");
2705        return 0;
2706    }
2707 
2708    /**
2709     * Returns the maximum size of a row (in bytes).
2710     *
2711     * @return 0 for limit is unknown
2712     */
2713    @Override
2714    public int getMaxRowSize() {
2715        debugCodeCall("getMaxRowSize");
2716        return 0;
2717    }
2718 
2719    /**
2720     * Returns the maximum length of a statement.
2721     *
2722     * @return 0 for limit is unknown
2723     */
2724    @Override
2725    public int getMaxStatementLength() {
2726        debugCodeCall("getMaxStatementLength");
2727        return 0;
2728    }
2729 
2730    /**
2731     * Returns the maximum number of open statements.
2732     *
2733     * @return 0 for limit is unknown
2734     */
2735    @Override
2736    public int getMaxStatements() {
2737        debugCodeCall("getMaxStatements");
2738        return 0;
2739    }
2740 
2741    /**
2742     * Returns the maximum length for a table name.
2743     *
2744     * @return 0 for limit is unknown
2745     */
2746    @Override
2747    public int getMaxTableNameLength() {
2748        debugCodeCall("getMaxTableNameLength");
2749        return 0;
2750    }
2751 
2752    /**
2753     * Returns the maximum number of tables in a SELECT.
2754     *
2755     * @return 0 for limit is unknown
2756     */
2757    @Override
2758    public int getMaxTablesInSelect() {
2759        debugCodeCall("getMaxTablesInSelect");
2760        return 0;
2761    }
2762 
2763    /**
2764     * Returns the maximum length for a user name.
2765     *
2766     * @return 0 for limit is unknown
2767     */
2768    @Override
2769    public int getMaxUserNameLength() {
2770        debugCodeCall("getMaxUserNameLength");
2771        return 0;
2772    }
2773 
2774    /**
2775     * Does the database support savepoints.
2776     *
2777     * @return true
2778     */
2779    @Override
2780    public boolean supportsSavepoints() {
2781        debugCodeCall("supportsSavepoints");
2782        return true;
2783    }
2784 
2785    /**
2786     * Does the database support named parameters.
2787     *
2788     * @return false
2789     */
2790    @Override
2791    public boolean supportsNamedParameters() {
2792        debugCodeCall("supportsNamedParameters");
2793        return false;
2794    }
2795 
2796    /**
2797     * Does the database support multiple open result sets.
2798     *
2799     * @return true
2800     */
2801    @Override
2802    public boolean supportsMultipleOpenResults() {
2803        debugCodeCall("supportsMultipleOpenResults");
2804        return true;
2805    }
2806 
2807    /**
2808     * Does the database support getGeneratedKeys.
2809     *
2810     * @return true
2811     */
2812    @Override
2813    public boolean supportsGetGeneratedKeys() {
2814        debugCodeCall("supportsGetGeneratedKeys");
2815        return true;
2816    }
2817 
2818    /**
2819     * [Not supported]
2820     */
2821    @Override
2822    public ResultSet getSuperTypes(String catalog, String schemaPattern,
2823            String typeNamePattern) throws SQLException {
2824        throw unsupported("superTypes");
2825    }
2826 
2827    /**
2828     * Get the list of super tables of a table. This method currently returns an
2829     * empty result set.
2830     * <ul>
2831     * <li>1 TABLE_CAT (String) table catalog</li>
2832     * <li>2 TABLE_SCHEM (String) table schema</li>
2833     * <li>3 TABLE_NAME (String) table name</li>
2834     * <li>4 SUPERTABLE_NAME (String) the name of the super table</li>
2835     * </ul>
2836     *
2837     * @param catalog null (to get all objects) or the catalog name
2838     * @param schemaPattern null (to get all objects) or a schema name
2839     *            (uppercase for unquoted names)
2840     * @param tableNamePattern null (to get all objects) or a table name pattern
2841     *            (uppercase for unquoted names)
2842     * @return an empty result set
2843     */
2844    @Override
2845    public ResultSet getSuperTables(String catalog, String schemaPattern,
2846            String tableNamePattern) throws SQLException {
2847        try {
2848            if (isDebugEnabled()) {
2849                debugCode("getSuperTables("
2850                        +quote(catalog)+", "
2851                        +quote(schemaPattern)+", "
2852                        +quote(tableNamePattern)+");");
2853            }
2854            checkClosed();
2855            PreparedStatement prep = conn.prepareAutoCloseStatement("SELECT "
2856                    + "CATALOG_NAME TABLE_CAT, "
2857                    + "CATALOG_NAME TABLE_SCHEM, "
2858                    + "CATALOG_NAME TABLE_NAME, "
2859                    + "CATALOG_NAME SUPERTABLE_NAME "
2860                    + "FROM INFORMATION_SCHEMA.CATALOGS "
2861                    + "WHERE FALSE");
2862            return prep.executeQuery();
2863        } catch (Exception e) {
2864            throw logAndConvert(e);
2865        }
2866    }
2867 
2868    /**
2869     * [Not supported]
2870     */
2871    @Override
2872    public ResultSet getAttributes(String catalog, String schemaPattern,
2873            String typeNamePattern, String attributeNamePattern)
2874            throws SQLException {
2875        throw unsupported("attributes");
2876    }
2877 
2878    /**
2879     * Does this database supports a result set holdability.
2880     *
2881     * @param holdability ResultSet.HOLD_CURSORS_OVER_COMMIT or
2882     *            CLOSE_CURSORS_AT_COMMIT
2883     * @return true if the holdability is ResultSet.CLOSE_CURSORS_AT_COMMIT
2884     */
2885    @Override
2886    public boolean supportsResultSetHoldability(int holdability) {
2887        debugCodeCall("supportsResultSetHoldability", holdability);
2888        return holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT;
2889    }
2890 
2891    /**
2892     * Gets the result set holdability.
2893     *
2894     * @return ResultSet.CLOSE_CURSORS_AT_COMMIT
2895     */
2896    @Override
2897    public int getResultSetHoldability() {
2898        debugCodeCall("getResultSetHoldability");
2899        return ResultSet.CLOSE_CURSORS_AT_COMMIT;
2900    }
2901 
2902    /**
2903     * Gets the major version of the database.
2904     *
2905     * @return the major version
2906     */
2907    @Override
2908    public int getDatabaseMajorVersion() {
2909        debugCodeCall("getDatabaseMajorVersion");
2910        return Constants.VERSION_MAJOR;
2911    }
2912 
2913    /**
2914     * Gets the minor version of the database.
2915     *
2916     * @return the minor version
2917     */
2918    @Override
2919    public int getDatabaseMinorVersion() {
2920        debugCodeCall("getDatabaseMinorVersion");
2921        return Constants.VERSION_MINOR;
2922    }
2923 
2924    /**
2925     * Gets the major version of the supported JDBC API.
2926     *
2927     * @return the major version (4)
2928     */
2929    @Override
2930    public int getJDBCMajorVersion() {
2931        debugCodeCall("getJDBCMajorVersion");
2932        return 4;
2933    }
2934 
2935    /**
2936     * Gets the minor version of the supported JDBC API.
2937     *
2938     * @return the minor version (0)
2939     */
2940    @Override
2941    public int getJDBCMinorVersion() {
2942        debugCodeCall("getJDBCMinorVersion");
2943        return 0;
2944    }
2945 
2946    /**
2947     * Gets the SQL State type.
2948     *
2949     * @return DatabaseMetaData.sqlStateSQL99
2950     */
2951    @Override
2952    public int getSQLStateType() {
2953        debugCodeCall("getSQLStateType");
2954        return DatabaseMetaData.sqlStateSQL99;
2955    }
2956 
2957    /**
2958     * Does the database make a copy before updating.
2959     *
2960     * @return false
2961     */
2962    @Override
2963    public boolean locatorsUpdateCopy() {
2964        debugCodeCall("locatorsUpdateCopy");
2965        return false;
2966    }
2967 
2968    /**
2969     * Does the database support statement pooling.
2970     *
2971     * @return false
2972     */
2973    @Override
2974    public boolean supportsStatementPooling() {
2975        debugCodeCall("supportsStatementPooling");
2976        return false;
2977    }
2978 
2979    // =============================================================
2980 
2981    private void checkClosed() {
2982        conn.checkClosed();
2983    }
2984 
2985    private static String getPattern(String pattern) {
2986        return pattern == null ? "%" : pattern;
2987    }
2988 
2989    private static String getSchemaPattern(String pattern) {
2990        return pattern == null ? "%" : pattern.length() == 0 ?
2991                Constants.SCHEMA_MAIN : pattern;
2992    }
2993 
2994    private static String getCatalogPattern(String catalogPattern) {
2995        // Workaround for OpenOffice: getColumns is called with "" as the
2996        // catalog
2997        return catalogPattern == null || catalogPattern.length() == 0 ?
2998                "%" : catalogPattern;
2999    }
3000 
3001    /**
3002     * Get the lifetime of a rowid.
3003     *
3004     * @return ROWID_UNSUPPORTED
3005     */
3006    @Override
3007    public RowIdLifetime getRowIdLifetime() {
3008        debugCodeCall("getRowIdLifetime");
3009        return RowIdLifetime.ROWID_UNSUPPORTED;
3010    }
3011 
3012    /**
3013     * Gets the list of schemas in the database.
3014     * The result set is sorted by TABLE_SCHEM.
3015     *
3016     * <ul>
3017     * <li>1 TABLE_SCHEM (String) schema name
3018     * </li><li>2 TABLE_CATALOG (String) catalog name
3019     * </li><li>3 IS_DEFAULT (boolean) if this is the default schema
3020     * </li></ul>
3021     *
3022     * @param catalogPattern null (to get all objects) or the catalog name
3023     * @param schemaPattern null (to get all objects) or a schema name
3024     *            (uppercase for unquoted names)
3025     * @return the schema list
3026     * @throws SQLException if the connection is closed
3027     */
3028    @Override
3029    public ResultSet getSchemas(String catalogPattern, String schemaPattern)
3030            throws SQLException {
3031        try {
3032            debugCodeCall("getSchemas(String,String)");
3033            checkClosed();
3034            PreparedStatement prep = conn
3035                    .prepareAutoCloseStatement("SELECT "
3036                            + "SCHEMA_NAME TABLE_SCHEM, "
3037                            + "CATALOG_NAME TABLE_CATALOG, "
3038                            +" IS_DEFAULT "
3039                            + "FROM INFORMATION_SCHEMA.SCHEMATA "
3040                            + "WHERE CATALOG_NAME LIKE ? ESCAPE ? "
3041                            + "AND SCHEMA_NAME LIKE ? ESCAPE ? "
3042                            + "ORDER BY SCHEMA_NAME");
3043            prep.setString(1, getCatalogPattern(catalogPattern));
3044            prep.setString(2, "\\");
3045            prep.setString(3, getSchemaPattern(schemaPattern));
3046            prep.setString(4, "\\");
3047            return prep.executeQuery();
3048        } catch (Exception e) {
3049            throw logAndConvert(e);
3050        }
3051    }
3052 
3053    /**
3054     * Returns whether the database supports calling functions using the call
3055     * syntax.
3056     *
3057     * @return true
3058     */
3059    @Override
3060    public boolean supportsStoredFunctionsUsingCallSyntax() {
3061        debugCodeCall("supportsStoredFunctionsUsingCallSyntax");
3062        return true;
3063    }
3064 
3065    /**
3066     * Returns whether an exception while auto commit is on closes all result
3067     * sets.
3068     *
3069     * @return false
3070     */
3071    @Override
3072    public boolean autoCommitFailureClosesAllResultSets() {
3073        debugCodeCall("autoCommitFailureClosesAllResultSets");
3074        return false;
3075    }
3076 
3077    /**
3078     * [Not supported] Returns the client info properties.
3079     */
3080    @Override
3081    public ResultSet getClientInfoProperties() throws SQLException {
3082        // we don't have any client properties, so return an empty result set
3083        return new SimpleResultSet();
3084    }
3085 
3086    /**
3087     * Return an object of this class if possible.
3088     *
3089     * @param iface the class
3090     * @return this
3091     */
3092    @Override
3093    @SuppressWarnings("unchecked")
3094    public <T> T unwrap(Class<T> iface) throws SQLException {
3095        if (isWrapperFor(iface)) {
3096            return (T) this;
3097        }
3098        throw DbException.getInvalidValueException("iface", iface);
3099    }
3100 
3101    /**
3102     * Checks if unwrap can return an object of this class.
3103     *
3104     * @param iface the class
3105     * @return whether or not the interface is assignable from this class
3106     */
3107    @Override
3108    public boolean isWrapperFor(Class<?> iface) throws SQLException {
3109        return iface != null && iface.isAssignableFrom(getClass());
3110    }
3111 
3112    /**
3113     * [Not supported] Gets the list of function columns.
3114     */
3115    @Override
3116    public ResultSet getFunctionColumns(String catalog, String schemaPattern,
3117            String functionNamePattern, String columnNamePattern)
3118            throws SQLException {
3119        throw unsupported("getFunctionColumns");
3120    }
3121 
3122    /**
3123     * [Not supported] Gets the list of functions.
3124     */
3125    @Override
3126    public ResultSet getFunctions(String catalog, String schemaPattern,
3127            String functionNamePattern) throws SQLException {
3128        throw unsupported("getFunctions");
3129    }
3130 
3131    /**
3132     * [Not supported]
3133     */
3134    //## Java 1.7 ##
3135    @Override
3136    public boolean generatedKeyAlwaysReturned() {
3137        return true;
3138    }
3139    //*/
3140 
3141    /**
3142     * [Not supported]
3143     *
3144     * @param catalog null (to get all objects) or the catalog name
3145     * @param schemaPattern null (to get all objects) or a schema name
3146     *            (uppercase for unquoted names)
3147     * @param tableNamePattern null (to get all objects) or a table name
3148     *            (uppercase for unquoted names)
3149     * @param columnNamePattern null (to get all objects) or a column name
3150     *            (uppercase for unquoted names)
3151     */
3152    //## Java 1.7 ##
3153    @Override
3154    public ResultSet getPseudoColumns(String catalog, String schemaPattern,
3155            String tableNamePattern, String columnNamePattern) {
3156        return null;
3157    }
3158    //*/
3159 
3160    /**
3161     * INTERNAL
3162     */
3163    @Override
3164    public String toString() {
3165        return getTraceObjectName() + ": " + conn;
3166    }
3167 
3168    private String getMode() throws SQLException {
3169        if (mode == null) {
3170            PreparedStatement prep = conn.prepareStatement(
3171                    "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?");
3172            prep.setString(1, "MODE");
3173            ResultSet rs = prep.executeQuery();
3174            rs.next();
3175            mode = rs.getString(1);
3176            prep.close();
3177        }
3178        return mode;
3179    }
3180 
3181}

[all classes][org.h2.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov