0001: /*
0002:
0003: Derby - Class org.apache.derby.impl.jdbc.EmbedDatabaseMetaData
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.impl.jdbc;
0023:
0024: import org.apache.derby.iapi.services.info.ProductVersionHolder;
0025:
0026: import org.apache.derby.iapi.services.monitor.Monitor;
0027:
0028: import org.apache.derby.iapi.services.sanity.SanityManager;
0029:
0030: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
0031:
0032: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
0033: import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
0034:
0035: import org.apache.derby.iapi.error.StandardException;
0036:
0037: import org.apache.derby.impl.sql.execute.GenericConstantActionFactory;
0038: import org.apache.derby.impl.sql.execute.GenericExecutionFactory;
0039:
0040: import org.apache.derby.iapi.reference.Limits;
0041: import org.apache.derby.iapi.reference.JDBC20Translation;
0042: import org.apache.derby.iapi.reference.JDBC30Translation;
0043:
0044: import java.util.Properties;
0045:
0046: import java.sql.DatabaseMetaData;
0047: import java.sql.Connection;
0048: import java.sql.PreparedStatement;
0049: import java.sql.SQLException;
0050: import java.sql.ResultSet;
0051: import java.sql.Types;
0052:
0053: import java.io.IOException;
0054: import java.io.InputStream;
0055:
0056: /**
0057: * This class provides information about the database as a whole.
0058: *
0059: * <P>Many of the methods here return lists of information in ResultSets.
0060: * You can use the normal ResultSet methods such as getString and getInt
0061: * to retrieve the data from these ResultSets. If a given form of
0062: * metadata is not available, these methods should throw a SQLException.
0063: *
0064: * <P>Some of these methods take arguments that are String patterns. These
0065: * arguments all have names such as fooPattern. Within a pattern String, "%"
0066: * means match any substring of 0 or more characters, and "_" means match
0067: * any one character. Only metadata entries matching the search pattern
0068: * are returned. If a search pattern argument is set to a null ref, it means
0069: * that argument's criteria should be dropped from the search.
0070: *
0071: * <P>A SQLException will be thrown if a driver does not support a meta
0072: * data method. In the case of methods that return a ResultSet,
0073: * either a ResultSet (which may be empty) is returned or a
0074: * SQLException is thrown.
0075: * <p>
0076: * This implementation gets instructions from the Database for how to satisfy
0077: * most requests for information. Each instruction is either a simple string
0078: * containing the desired information, or the text of a query that may be
0079: * executed on the database connection to gather the information. We get the
0080: * instructions via an "InstructionReader," which requires the database
0081: * Connection for initialization.
0082: * <p>
0083: * Those few pieces of metadata that are related to the driver, rather than the
0084: * database, come from a separate InstructionReader. Note that in that case it
0085: * probably doesn't make sense to allow an instruction to specify a query.
0086: *
0087: * @author ames
0088: */
0089: public class EmbedDatabaseMetaData extends ConnectionChild implements
0090: DatabaseMetaData, java.security.PrivilegedAction {
0091:
0092: /*
0093: ** Property and values related to using
0094: ** stored prepared statements for metatdata.
0095: */
0096:
0097: private final String url;
0098:
0099: /*
0100: ** Set to true if metadata is off
0101: */
0102:
0103: private GenericConstantActionFactory constantActionFactory;
0104:
0105: //////////////////////////////////////////////////////////////
0106: //
0107: // CONSTRUCTORS
0108: //
0109: //////////////////////////////////////////////////////////////
0110: /**
0111: @exception SQLException on error
0112: */
0113: public EmbedDatabaseMetaData(EmbedConnection connection, String url)
0114: throws SQLException {
0115:
0116: super (connection);
0117: this .url = url;
0118:
0119: }
0120:
0121: /** Cached query descriptions from metadata.properties. */
0122: private static Properties queryDescriptions;
0123: /** Cached query descriptions from metadata_net.properties. */
0124: private static Properties queryDescriptions_net;
0125:
0126: /**
0127: * Return all queries found in either metadata.properties or
0128: * metadata_net.properties.
0129: *
0130: * @param net if <code>true</code>, read metadata_net.properties;
0131: * otherwise, read metadata.properties.
0132: * @return a <code>Properties</code> value with the queries
0133: */
0134: private Properties getQueryDescriptions(boolean net) {
0135: Properties p = net ? queryDescriptions_net : queryDescriptions;
0136: if (p != null) {
0137: return p;
0138: }
0139: loadQueryDescriptions();
0140: return net ? queryDescriptions_net : queryDescriptions;
0141: }
0142:
0143: /**
0144: * Read the query descriptions from metadata.properties and
0145: * metadata_net.properties. This method must be invoked from
0146: * within a privileged block.
0147: */
0148: private void PBloadQueryDescriptions() {
0149: String[] files = { "metadata.properties",
0150: "/org/apache/derby/impl/sql/catalog/metadata_net.properties" };
0151: Properties[] props = new Properties[files.length];
0152: for (int i = 0; i < files.length; ++i) {
0153: try {
0154: props[i] = new Properties();
0155: // SECURITY PERMISSION - IP3
0156: InputStream is = getClass().getResourceAsStream(
0157: files[i]);
0158: props[i].load(is);
0159: is.close();
0160: } catch (IOException ioe) {
0161: if (SanityManager.DEBUG) {
0162: SanityManager.THROWASSERT("Error reading "
0163: + files[i], ioe);
0164: }
0165: }
0166: }
0167: queryDescriptions = props[0];
0168: queryDescriptions_net = props[1];
0169: }
0170:
0171: //////////////////////////////////////////////////////////////
0172: //
0173: // DatabaseMetaData interface
0174: //
0175: //////////////////////////////////////////////////////////////
0176:
0177: //----------------------------------------------------------------------
0178: // First, a variety of minor information about the target database.
0179:
0180: /**
0181: * Can all the procedures returned by getProcedures be called by the
0182: * current user?
0183: *
0184: * @return true if so
0185: */
0186: public boolean allProceduresAreCallable() {
0187: return true;
0188: }
0189:
0190: /**
0191: * Can all the tables returned by getTable be SELECTed by the
0192: * current user?
0193: *
0194: * @return true if so
0195: */
0196: public boolean allTablesAreSelectable() {
0197: return true;
0198: }
0199:
0200: /**
0201: * What's the url for this database?
0202: *
0203: * @return the url or null if it can't be generated
0204: */
0205: public final String getURL() {
0206:
0207: if (url == null)
0208: return url;
0209: int attributeStart = url.indexOf(';');
0210: if (attributeStart == -1)
0211: return url;
0212: else
0213: return url.substring(0, attributeStart);
0214: }
0215:
0216: /**
0217: * What's our user name as known to the database?
0218: *
0219: * @return our database user name
0220: */
0221: public String getUserName() {
0222: return (getEmbedConnection().getTR().getUserName());
0223: }
0224:
0225: /**
0226: * Is the database in read-only mode?
0227: *
0228: * @return true if so
0229: */
0230: public boolean isReadOnly() {
0231: return getLanguageConnectionContext().getDatabase()
0232: .isReadOnly();
0233: }
0234:
0235: /**
0236: * Are NULL values sorted high?
0237: *
0238: * @return true if so
0239: */
0240: public boolean nullsAreSortedHigh() {
0241: return true;
0242: }
0243:
0244: /**
0245: * Are NULL values sorted low?
0246: *
0247: * @return true if so
0248: */
0249: public boolean nullsAreSortedLow() {
0250: return false;
0251: }
0252:
0253: /**
0254: * Are NULL values sorted at the start regardless of sort order?
0255: *
0256: * @return true if so
0257: */
0258: public boolean nullsAreSortedAtStart() {
0259: return false;
0260: }
0261:
0262: /**
0263: * Are NULL values sorted at the end regardless of sort order?
0264: *
0265: * @return true if so
0266: */
0267: public boolean nullsAreSortedAtEnd() {
0268: return false;
0269: }
0270:
0271: /**
0272: * What's the name of this database product?
0273: *
0274: * @return database product name
0275: */
0276: public String getDatabaseProductName() {
0277: return Monitor.getMonitor().getEngineVersion().getProductName();
0278: }
0279:
0280: /**
0281: * What's the version of this database product?
0282: *
0283: * @return database version
0284: */
0285: public String getDatabaseProductVersion() {
0286: ProductVersionHolder myPVH = Monitor.getMonitor()
0287: .getEngineVersion();
0288:
0289: return myPVH.getVersionBuildString(true);
0290: }
0291:
0292: /**
0293: * What's the name of this JDBC driver?
0294: *
0295: * @return JDBC driver name
0296: */
0297: public String getDriverName() {
0298: return "Apache Derby Embedded JDBC Driver";
0299: }
0300:
0301: /**
0302: * What's the version of this JDBC driver?
0303: *
0304: * @return JDBC driver version
0305: */
0306: public String getDriverVersion() {
0307: return getDatabaseProductVersion();
0308: }
0309:
0310: /**
0311: * What's this JDBC driver's major version number?
0312: *
0313: * @return JDBC driver major version
0314: */
0315: public int getDriverMajorVersion() {
0316: return getEmbedConnection().getLocalDriver().getMajorVersion();
0317: }
0318:
0319: /**
0320: * What's this JDBC driver's minor version number?
0321: *
0322: * @return JDBC driver minor version number
0323: */
0324: public int getDriverMinorVersion() {
0325: return getEmbedConnection().getLocalDriver().getMinorVersion();
0326: }
0327:
0328: /**
0329: * Does the database store tables in a local file?
0330: *
0331: * @return true if so
0332: */
0333: public boolean usesLocalFiles() {
0334: return true;
0335: }
0336:
0337: /**
0338: * Does the database use a file for each table?
0339: *
0340: * @return true if the database uses a local file for each table
0341: */
0342: public boolean usesLocalFilePerTable() {
0343: return true;
0344: }
0345:
0346: /**
0347: * Does the database treat mixed case unquoted SQL identifiers as
0348: * case sensitive and as a result store them in mixed case?
0349: *
0350: * A JDBC-Compliant driver will always return false.
0351: *
0352: * @return true if so
0353: */
0354: public boolean supportsMixedCaseIdentifiers() {
0355: return false;
0356: }
0357:
0358: /**
0359: * Does the database treat mixed case unquoted SQL identifiers as
0360: * case insensitive and store them in upper case?
0361: *
0362: * @return true if so
0363: */
0364: public boolean storesUpperCaseIdentifiers() {
0365: return true;
0366: }
0367:
0368: /**
0369: * Does the database treat mixed case unquoted SQL identifiers as
0370: * case insensitive and store them in lower case?
0371: *
0372: * @return true if so
0373: */
0374: public boolean storesLowerCaseIdentifiers() {
0375: return false;
0376: }
0377:
0378: /**
0379: * Does the database treat mixed case unquoted SQL identifiers as
0380: * case insensitive and store them in mixed case?
0381: *
0382: * @return true if so
0383: */
0384: public boolean storesMixedCaseIdentifiers() {
0385: return false;
0386: }
0387:
0388: /**
0389: * Does the database treat mixed case quoted SQL identifiers as
0390: * case sensitive and as a result store them in mixed case?
0391: *
0392: * A JDBC-Compliant driver will always return true.
0393: *
0394: * @return true if so
0395: */
0396: public boolean supportsMixedCaseQuotedIdentifiers() {
0397: return true;
0398: }
0399:
0400: /**
0401: * Does the database treat mixed case quoted SQL identifiers as
0402: * case insensitive and store them in upper case?
0403: *
0404: * @return true if so
0405: */
0406: public boolean storesUpperCaseQuotedIdentifiers() {
0407: return false;
0408: }
0409:
0410: /**
0411: * Does the database treat mixed case quoted SQL identifiers as
0412: * case insensitive and store them in lower case?
0413: *
0414: * @return true if so
0415: */
0416: public boolean storesLowerCaseQuotedIdentifiers() {
0417: return false;
0418: }
0419:
0420: /**
0421: * Does the database treat mixed case quoted SQL identifiers as
0422: * case insensitive and store them in mixed case?
0423: *
0424: * @return true if so
0425: */
0426: public boolean storesMixedCaseQuotedIdentifiers() {
0427: return true;
0428: }
0429:
0430: /**
0431: * What's the string used to quote SQL identifiers?
0432: * This returns a space " " if identifier quoting isn't supported.
0433: *
0434: * A JDBC-Compliant driver always uses a double quote character.
0435: *
0436: * @return the quoting string
0437: */
0438: public String getIdentifierQuoteString() {
0439: return "\"";
0440: }
0441:
0442: /**
0443: * Get a comma separated list of all a database's SQL keywords
0444: * that are NOT also SQL92 keywords.
0445: includes reserved and non-reserved keywords.
0446:
0447: * @return the list
0448: */
0449: public String getSQLKeywords() {
0450: return "ALIAS,BIGINT,BOOLEAN,CALL,CLASS,COPY,DB2J_DEBUG,EXECUTE,EXPLAIN,FILE,FILTER,"
0451: + "GETCURRENTCONNECTION,INDEX,INSTANCEOF,METHOD,NEW,OFF,PROPERTIES,PUBLICATION,RECOMPILE,"
0452: + "REFRESH,RENAME,RUNTIMESTATISTICS,STATEMENT,STATISTICS,TIMING,WAIT";
0453: }
0454:
0455: /**
0456: * Get a comma separated list of JDBC escaped numeric functions.
0457: * Must be a complete or sub set of functions in appendix C.1
0458: * @return the list
0459: */
0460: public String getNumericFunctions() {
0461: return "ABS,ACOS,ASIN,ATAN,CEILING,COS,DEGREES,EXP,FLOOR,LOG,LOG10,MOD,PI,RADIANS,SIN,SQRT,TAN";
0462: }
0463:
0464: /**
0465: * Get a comma separated list of JDBC escaped string functions.
0466: * Must be a complete or sub set of functions in appendix C.2
0467: * of JDBC 3.0 specification.
0468: * @return the list
0469: */
0470: public String getStringFunctions() {
0471: return "CONCAT,LENGTH,LCASE,LOCATE,LTRIM,RTRIM,SUBSTRING,UCASE";
0472: }
0473:
0474: /**
0475: * Get a comma separated list of JDBC escaped system functions.
0476: * Must be a complete or sub set of functions in appendix C.4
0477: * of JDBC 3.0 specification.
0478: * @return the list
0479: */
0480: public String getSystemFunctions() {
0481: return "USER";
0482: }
0483:
0484: /**
0485: * Get a comma separated list of JDBC escaped time date functions.
0486: * Must be a complete or sub set of functions in appendix C.3
0487: * of JDBC 3.0 specification.
0488: * @return the list
0489: */
0490: public String getTimeDateFunctions() {
0491: return "CURDATE,CURTIME,HOUR,MINUTE,MONTH,SECOND,TIMESTAMPADD,TIMESTAMPDIFF,YEAR";
0492: }
0493:
0494: /**
0495: * This is the string that can be used to escape '_' or '%' in
0496: * the string pattern style catalog search parameters.
0497: we have no default escape value, so = is the end of the next line
0498: * <P>The '_' character represents any single character.
0499: * <P>The '%' character represents any sequence of zero or
0500: * more characters.
0501: * @return the string used to escape wildcard characters
0502: */
0503: public String getSearchStringEscape() {
0504: return "";
0505: }
0506:
0507: /**
0508: * Get all the "extra" characters that can be used in unquoted
0509: * identifier names (those beyond a-z, A-Z, 0-9 and _).
0510: *
0511: * @return the string containing the extra characters
0512: */
0513: public String getExtraNameCharacters() {
0514: return "";
0515: }
0516:
0517: //--------------------------------------------------------------------
0518: // Functions describing which features are supported.
0519:
0520: /**
0521: * Is "ALTER TABLE" with add column supported?
0522: *
0523: * @return true if so
0524: */
0525: public boolean supportsAlterTableWithAddColumn() {
0526: return true;
0527: }
0528:
0529: /**
0530: * Is "ALTER TABLE" with drop column supported?
0531: *
0532: * @return true if so
0533: */
0534: public boolean supportsAlterTableWithDropColumn() {
0535: return true;
0536: }
0537:
0538: /**
0539: * Is column aliasing supported?
0540: *
0541: * <P>If so, the SQL AS clause can be used to provide names for
0542: * computed columns or to provide alias names for columns as
0543: * required.
0544: *
0545: * A JDBC-Compliant driver always returns true.
0546: *
0547: * @return true if so
0548: */
0549: public boolean supportsColumnAliasing() {
0550: return true;
0551: }
0552:
0553: /**
0554: * Are concatenations between NULL and non-NULL values NULL?
0555: *
0556: * A JDBC-Compliant driver always returns true.
0557: *
0558: * @return true if so
0559: */
0560: public boolean nullPlusNonNullIsNull() {
0561: return true;
0562: }
0563:
0564: /**
0565: * Is the CONVERT function between SQL types supported?
0566: *
0567: * @return true if so
0568: */
0569: public boolean supportsConvert() {
0570: return true;
0571: }
0572:
0573: /**
0574: * Is CONVERT between the given SQL types supported?
0575: *
0576: * @param fromType the type to convert from
0577: * @param toType the type to convert to
0578: * @return true if so
0579: * @see Types
0580: */
0581: public boolean supportsConvert(int fromType, int toType) {
0582: /*
0583: * at the moment we don't support CONVERT at all, so we take the easy
0584: * way out. Eventually we need to figure out how to handle this
0585: * cleanly.
0586: */
0587: return false;
0588: }
0589:
0590: /**
0591: * Are table correlation names supported?
0592: *
0593: * A JDBC-Compliant driver always returns true.
0594: *
0595: * @return true if so
0596: */
0597: public boolean supportsTableCorrelationNames() {
0598: return true;
0599: }
0600:
0601: /**
0602: * If table correlation names are supported, are they restricted
0603: * to be different from the names of the tables?
0604: *
0605: * @return true if so
0606: */
0607: public boolean supportsDifferentTableCorrelationNames() {
0608: return true;
0609: }
0610:
0611: /**
0612: * Are expressions in "ORDER BY" lists supported?
0613: *
0614: * @return true if so
0615: */
0616: public boolean supportsExpressionsInOrderBy() {
0617: return false;
0618: }
0619:
0620: /**
0621: * Can an "ORDER BY" clause use columns not in the SELECT?
0622: *
0623: * @return true if so
0624: */
0625: public boolean supportsOrderByUnrelated() {
0626: return false;
0627: }
0628:
0629: /**
0630: * Is some form of "GROUP BY" clause supported?
0631: *
0632: * @return true if so
0633: */
0634: public boolean supportsGroupBy() {
0635: return true;
0636: }
0637:
0638: /**
0639: * Can a "GROUP BY" clause use columns not in the SELECT?
0640: *
0641: * @return true if so
0642: */
0643: public boolean supportsGroupByUnrelated() {
0644: return true;
0645: }
0646:
0647: /**
0648: * Can a "GROUP BY" clause add columns not in the SELECT
0649: * provided it specifies all the columns in the SELECT?
0650: *
0651: * @return true if so
0652: */
0653: public boolean supportsGroupByBeyondSelect() {
0654: return true;
0655: }
0656:
0657: /**
0658: * Is the escape character in "LIKE" clauses supported?
0659: *
0660: * A JDBC-Compliant driver always returns true.
0661: *
0662: * @return true if so
0663: */
0664: public boolean supportsLikeEscapeClause() {
0665: return true;
0666: }
0667:
0668: /**
0669: * Are multiple ResultSets from a single execute supported?
0670: *
0671: * @return true if so
0672: */
0673: public boolean supportsMultipleResultSets() {
0674: return true;
0675: }
0676:
0677: /**
0678: * Can we have multiple transactions open at once (on different
0679: * connections)?
0680: *
0681: * @return true if so
0682: */
0683: public boolean supportsMultipleTransactions() {
0684: return true;
0685: }
0686:
0687: /**
0688: * Can columns be defined as non-nullable?
0689: *
0690: * A JDBC-Compliant driver always returns true.
0691: *
0692: * @return true if so
0693: */
0694: public boolean supportsNonNullableColumns() {
0695: return true;
0696: }
0697:
0698: /**
0699: * Is the ODBC Minimum SQL grammar supported?
0700: *
0701: * All JDBC-Compliant drivers must return true.
0702: *
0703: * @return true if so
0704: */
0705: public boolean supportsMinimumSQLGrammar() {
0706: return true;
0707: }
0708:
0709: /**
0710: * Is the ODBC Core SQL grammar supported?
0711: *
0712: * @return true if so
0713: */
0714: public boolean supportsCoreSQLGrammar() {
0715: return false;
0716: }
0717:
0718: /**
0719: * Is the ODBC Extended SQL grammar supported?
0720: *
0721: * @return true if so
0722: */
0723: public boolean supportsExtendedSQLGrammar() {
0724: return false;
0725: }
0726:
0727: /**
0728: * Is the ANSI92 entry level SQL grammar supported?
0729: *
0730: * All JDBC-Compliant drivers must return true.
0731: *
0732: * @return true if so
0733: */
0734: public boolean supportsANSI92EntryLevelSQL() {
0735: return false;
0736: }
0737:
0738: /**
0739: * Is the ANSI92 intermediate SQL grammar supported?
0740: *
0741: * @return true if so
0742: *
0743: */
0744: public boolean supportsANSI92IntermediateSQL() {
0745: return false;
0746: }
0747:
0748: /**
0749: * Is the ANSI92 full SQL grammar supported?
0750: *
0751: * @return true if so
0752: *
0753: */
0754: public boolean supportsANSI92FullSQL() {
0755: return false;
0756: }
0757:
0758: /**
0759: * Is the SQL Integrity Enhancement Facility supported?
0760: *
0761: * @return true if so
0762: *
0763: */
0764: public boolean supportsIntegrityEnhancementFacility() {
0765: return false;
0766: }
0767:
0768: /**
0769: * Is some form of outer join supported?
0770: *
0771: * @return true if so
0772: *
0773: */
0774: public boolean supportsOuterJoins() {
0775: return true;
0776: }
0777:
0778: /**
0779: * Are full nested outer joins supported?
0780: *
0781: * @return true if so
0782: *
0783: */
0784: public boolean supportsFullOuterJoins() {
0785: return false;
0786: }
0787:
0788: /**
0789: * Is there limited support for outer joins? (This will be true
0790: * if supportFullOuterJoins is true.)
0791: *
0792: * @return true if so
0793: *
0794: */
0795: public boolean supportsLimitedOuterJoins() {
0796: return true;
0797: }
0798:
0799: /**
0800: * What's the database vendor's preferred term for "schema"?
0801: *
0802: * @return the vendor term
0803: *
0804: */
0805: public String getSchemaTerm() {
0806: return "SCHEMA";
0807: }
0808:
0809: /**
0810: * What's the database vendor's preferred term for "procedure"?
0811: *
0812: * @return the vendor term
0813: *
0814: */
0815: public String getProcedureTerm() {
0816: return "PROCEDURE";
0817: }
0818:
0819: /**
0820: * What's the database vendor's preferred term for "catalog"?
0821: *
0822: * @return the vendor term
0823: *
0824: */
0825: public String getCatalogTerm() {
0826: return "CATALOG";
0827: }
0828:
0829: /**
0830: * Does a catalog appear at the start of a qualified table name?
0831: * (Otherwise it appears at the end)
0832: *
0833: * @return true if it appears at the start
0834: *
0835: */
0836: public boolean isCatalogAtStart() {
0837: return false;
0838: }
0839:
0840: /**
0841: * What's the separator between catalog and table name?
0842: *
0843: * @return the separator string
0844: *
0845: */
0846: public String getCatalogSeparator() {
0847: return "";
0848: }
0849:
0850: /**
0851: * Can a schema name be used in a data manipulation statement?
0852: *
0853: * @return true if so
0854: *
0855: */
0856: public boolean supportsSchemasInDataManipulation() {
0857: return true;
0858: }
0859:
0860: /**
0861: * Can a schema name be used in a procedure call statement?
0862: *
0863: * @return true if so
0864: *
0865: */
0866: public boolean supportsSchemasInProcedureCalls() {
0867: return true;
0868: }
0869:
0870: /**
0871: * Can a schema name be used in a table definition statement?
0872: *
0873: * @return true if so
0874: *
0875: */
0876: public boolean supportsSchemasInTableDefinitions() {
0877: return true;
0878: }
0879:
0880: /**
0881: * Can a schema name be used in an index definition statement?
0882: *
0883: * @return true if so
0884: */
0885: public boolean supportsSchemasInIndexDefinitions() {
0886: return true;
0887: }
0888:
0889: /**
0890: * Can a schema name be used in a privilege definition statement?
0891: *
0892: * @return true if so
0893: *
0894: */
0895: public boolean supportsSchemasInPrivilegeDefinitions() {
0896: return true;
0897: }
0898:
0899: /**
0900: * Can a catalog name be used in a data manipulation statement?
0901: *
0902: * @return true if so
0903: *
0904: */
0905: public boolean supportsCatalogsInDataManipulation() {
0906: return false;
0907: }
0908:
0909: /**
0910: * Can a catalog name be used in a procedure call statement?
0911: *
0912: * @return true if so
0913: *
0914: */
0915: public boolean supportsCatalogsInProcedureCalls() {
0916: return false;
0917: }
0918:
0919: /**
0920: * Can a catalog name be used in a table definition statement?
0921: *
0922: * @return true if so
0923: *
0924: */
0925: public boolean supportsCatalogsInTableDefinitions() {
0926: return false;
0927: }
0928:
0929: /**
0930: * Can a catalog name be used in an index definition statement?
0931: *
0932: * @return true if so
0933: */
0934: public boolean supportsCatalogsInIndexDefinitions() {
0935: return false;
0936: }
0937:
0938: /**
0939: * Can a catalog name be used in a privilege definition statement?
0940: *
0941: * @return true if so
0942: */
0943: public boolean supportsCatalogsInPrivilegeDefinitions() {
0944: return false;
0945: }
0946:
0947: /**
0948: * Is positioned DELETE supported?
0949: *
0950: * @return true if so
0951: */
0952: public boolean supportsPositionedDelete() {
0953: return true;
0954: }
0955:
0956: /**
0957: * Is positioned UPDATE supported?
0958: *
0959: * @return true if so
0960: */
0961: public boolean supportsPositionedUpdate() {
0962: return true;
0963: }
0964:
0965: /**
0966: * Is SELECT for UPDATE supported?
0967: *
0968: * @return true if so
0969: */
0970: public boolean supportsSelectForUpdate() {
0971: return true;
0972: }
0973:
0974: /**
0975: * Are stored procedure calls using the stored procedure escape
0976: * syntax supported?
0977: *
0978: * @return true if so
0979: */
0980: public boolean supportsStoredProcedures() {
0981: return true;
0982: }
0983:
0984: /**
0985: * Are subqueries in comparison expressions supported?
0986: *
0987: * A JDBC-Compliant driver always returns true.
0988: *
0989: * @return true if so
0990: */
0991: public boolean supportsSubqueriesInComparisons() {
0992: return true;
0993: }
0994:
0995: /**
0996: * Are subqueries in 'exists' expressions supported?
0997: *
0998: * A JDBC-Compliant driver always returns true.
0999: *
1000: * @return true if so
1001: */
1002: public boolean supportsSubqueriesInExists() {
1003: return true;
1004: }
1005:
1006: /**
1007: * Are subqueries in 'in' statements supported?
1008: *
1009: * A JDBC-Compliant driver always returns true.
1010: *
1011: * @return true if so
1012: */
1013: public boolean supportsSubqueriesInIns() {
1014: return true;
1015: }
1016:
1017: /**
1018: * Are subqueries in quantified expressions supported?
1019: *
1020: * A JDBC-Compliant driver always returns true.
1021: *
1022: * @return true if so
1023: */
1024: public boolean supportsSubqueriesInQuantifieds() {
1025: return true;
1026: }
1027:
1028: /**
1029: * Are correlated subqueries supported?
1030: *
1031: * A JDBC-Compliant driver always returns true.
1032: *
1033: * @return true if so
1034: */
1035: public boolean supportsCorrelatedSubqueries() {
1036: return true;
1037: }
1038:
1039: /**
1040: * Is SQL UNION supported?
1041: *
1042: * @return true if so
1043: */
1044: public boolean supportsUnion() {
1045: return true;
1046: }
1047:
1048: /**
1049: * Is SQL UNION ALL supported?
1050: *
1051: * @return true if so
1052: */
1053: public boolean supportsUnionAll() {
1054: return true;
1055: }
1056:
1057: /**
1058: * Can cursors remain open across commits?
1059: *
1060: * @return true if cursors always remain open; false if they might not remain open
1061: */
1062: //returns false because Derby does not support cursors that are open across commits for XA transactions.
1063: public boolean supportsOpenCursorsAcrossCommit() {
1064: return false;
1065: }
1066:
1067: /**
1068: * Can cursors remain open across rollbacks?
1069: *
1070: * @return true if cursors always remain open; false if they might not remain open
1071: */
1072: public boolean supportsOpenCursorsAcrossRollback() {
1073: return false;
1074: }
1075:
1076: /**
1077: * Can statements remain open across commits?
1078: *
1079: * @return true if statements always remain open; false if they might not remain open
1080: */
1081: public boolean supportsOpenStatementsAcrossCommit() {
1082: return true;
1083: }
1084:
1085: /**
1086: * Can statements remain open across rollbacks?
1087: *
1088: * @return true if statements always remain open; false if they might not remain open
1089: */
1090: public boolean supportsOpenStatementsAcrossRollback() {
1091: return false;
1092: }
1093:
1094: //----------------------------------------------------------------------
1095: // The following group of methods exposes various limitations
1096: // based on the target database with the current driver.
1097: // Unless otherwise specified, a result of zero means there is no
1098: // limit, or the limit is not known.
1099:
1100: /**
1101: * How many hex characters can you have in an inline binary literal?
1102: *
1103: * @return max literal length
1104: */
1105: public int getMaxBinaryLiteralLength() {
1106: return 0;
1107: }
1108:
1109: /**
1110: * What's the max length for a character literal?
1111: *
1112: * @return max literal length
1113: */
1114: public int getMaxCharLiteralLength() {
1115: return 0;
1116: }
1117:
1118: /**
1119: * What's the limit on column name length?
1120: *
1121: * @return max literal length
1122: */
1123: public int getMaxColumnNameLength() {
1124: return Limits.MAX_IDENTIFIER_LENGTH;
1125: }
1126:
1127: /**
1128: * What's the maximum number of columns in a "GROUP BY" clause?
1129: *
1130: * @return max number of columns
1131: */
1132: public int getMaxColumnsInGroupBy() {
1133: return 0;
1134: }
1135:
1136: /**
1137: * What's the maximum number of columns allowed in an index?
1138: *
1139: * @return max columns
1140: */
1141: public int getMaxColumnsInIndex() {
1142: return 0;
1143: }
1144:
1145: /**
1146: * What's the maximum number of columns in an "ORDER BY" clause?
1147: *
1148: * @return max columns
1149: */
1150: public int getMaxColumnsInOrderBy() {
1151: return 0;
1152: }
1153:
1154: /**
1155: * What's the maximum number of columns in a "SELECT" list?
1156: *
1157: * we don't have a limit...
1158: *
1159: * @return max columns
1160: */
1161: public int getMaxColumnsInSelect() {
1162: return 0;
1163: }
1164:
1165: /**
1166: * What's the maximum number of columns in a table?
1167: *
1168: * @return max columns
1169: */
1170: public int getMaxColumnsInTable() {
1171: return 0;
1172: }
1173:
1174: /**
1175: * How many active connections can we have at a time to this database?
1176: *
1177: * @return max connections
1178: */
1179: public int getMaxConnections() {
1180: return 0;
1181: }
1182:
1183: /**
1184: * What's the maximum cursor name length?
1185: *
1186: * @return max cursor name length in bytes
1187: */
1188: public int getMaxCursorNameLength() {
1189: return Limits.MAX_IDENTIFIER_LENGTH;
1190: }
1191:
1192: /**
1193: * What's the maximum length of an index (in bytes)?
1194: *
1195: * @return max index length in bytes
1196: */
1197: public int getMaxIndexLength() {
1198: return 0;
1199: }
1200:
1201: /**
1202: * What's the maximum length allowed for a schema name?
1203: *
1204: * @return max name length in bytes
1205: */
1206: public int getMaxSchemaNameLength() {
1207: return Limits.MAX_IDENTIFIER_LENGTH;
1208: }
1209:
1210: /**
1211: * What's the maximum length of a procedure name?
1212: *
1213: * @return max name length in bytes
1214: */
1215: public int getMaxProcedureNameLength() {
1216: return Limits.MAX_IDENTIFIER_LENGTH;
1217: }
1218:
1219: /**
1220: * What's the maximum length of a catalog name?
1221: *
1222: * @return max name length in bytes
1223: */
1224: public int getMaxCatalogNameLength() {
1225: return 0;
1226: }
1227:
1228: /**
1229: * What's the maximum length of a single row?
1230: *
1231: * @return max row size in bytes
1232: */
1233: public int getMaxRowSize() {
1234: return 0;
1235: }
1236:
1237: /**
1238: * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
1239: * blobs?
1240: *
1241: * @return true if so
1242: */
1243: public boolean doesMaxRowSizeIncludeBlobs() {
1244: return true;
1245: }
1246:
1247: /**
1248: * What's the maximum length of a SQL statement?
1249: *
1250: * @return max length in bytes
1251: */
1252: public int getMaxStatementLength() {
1253: return 0;
1254: }
1255:
1256: /**
1257: * How many active statements can we have open at one time to this
1258: * database?
1259: *
1260: * @return the maximum
1261: */
1262: public int getMaxStatements() {
1263: return 0;
1264: }
1265:
1266: /**
1267: * What's the maximum length of a table name?
1268: *
1269: * @return max name length in bytes
1270: */
1271: public int getMaxTableNameLength() {
1272: return Limits.MAX_IDENTIFIER_LENGTH;
1273: }
1274:
1275: /**
1276: * What's the maximum number of tables in a SELECT?
1277: *
1278: * @return the maximum
1279: */
1280: public int getMaxTablesInSelect() {
1281: return 0;
1282: }
1283:
1284: /**
1285: * What's the maximum length of a user name?
1286: *
1287: * @return max name length in bytes
1288: */
1289: public int getMaxUserNameLength() {
1290: return Limits.DB2_MAX_USERID_LENGTH;
1291: }
1292:
1293: //----------------------------------------------------------------------
1294:
1295: /**
1296: * What's the database's default transaction isolation level? The
1297: * values are defined in java.sql.Connection.
1298: *
1299: * @return the default isolation level
1300: * @see Connection
1301: */
1302: public int getDefaultTransactionIsolation() {
1303: return java.sql.Connection.TRANSACTION_READ_COMMITTED;
1304: }
1305:
1306: /**
1307: * Are transactions supported? If not, commit is a noop and the
1308: * isolation level is TRANSACTION_NONE.
1309: *
1310: * @return true if transactions are supported
1311: */
1312: public boolean supportsTransactions() {
1313: return true;
1314: }
1315:
1316: /**
1317: * Does the database support the given transaction isolation level?
1318: *
1319: * DatabaseMetaData.supportsTransactionIsolation() should return false for
1320: * isolation levels that are not supported even if a higher level can be
1321: * substituted.
1322: *
1323: * @param level the values are defined in java.sql.Connection
1324: * @return true if so
1325: * @see Connection
1326: */
1327: public boolean supportsTransactionIsolationLevel(int level) {
1328: // REMIND: This is hard-coded for the moment because it doesn't nicely
1329: // fit within the framework we've set up for the rest of these values.
1330: // Part of the reason is that it has a parameter, so it's not just a
1331: // simple value look-up. Some ideas for the future on how to make this
1332: // not hard-coded:
1333: // - code it as a query: "select true from <something> where ? in
1334: // (a,b,c)" where a,b,c are the supported isolation levels. The
1335: // parameter would be set to "level". This seems awfully awkward.
1336: // - somehow what you'd really like is to enable the instructions
1337: // file to contain the list, or set, of supported isolation
1338: // levels. Something like:
1339: // supportsTr...ionLevel=SERIALIZABLE | REPEATABLE_READ | ...
1340: // That would take some more code that doesn't seem worthwhile at
1341: // the moment for this one case.
1342:
1343: /*
1344: REMIND: this could be moved into a query that is e.g.
1345: VALUES ( ? in (8,...) )
1346: so that database could control the list of supported
1347: isolations. For now, it's hard coded, and just the one.
1348: */
1349:
1350: return (level == Connection.TRANSACTION_SERIALIZABLE
1351: || level == Connection.TRANSACTION_REPEATABLE_READ
1352: || level == Connection.TRANSACTION_READ_COMMITTED || level == Connection.TRANSACTION_READ_UNCOMMITTED);
1353: }
1354:
1355: /**
1356: * Are both data definition and data manipulation statements
1357: * within a transaction supported?
1358: *
1359: * @return true if so
1360: */
1361: public boolean supportsDataDefinitionAndDataManipulationTransactions() {
1362: return true;
1363: }
1364:
1365: /**
1366: * Are only data manipulation statements within a transaction
1367: * supported?
1368: *
1369: * @return true if so
1370: */
1371: public boolean supportsDataManipulationTransactionsOnly() {
1372: return false;
1373: }
1374:
1375: /**
1376: * Does a data definition statement within a transaction force the
1377: * transaction to commit?
1378: *
1379: * @return true if so
1380: *
1381: */
1382: public boolean dataDefinitionCausesTransactionCommit() {
1383: return false;
1384: }
1385:
1386: /**
1387: * Is a data definition statement within a transaction ignored?
1388: *
1389: * @return true if so
1390: *
1391: */
1392: public boolean dataDefinitionIgnoredInTransactions() {
1393: return false;
1394: }
1395:
1396: /**
1397: * Get a description of stored procedures available in a
1398: * catalog.
1399: *
1400: * <P>Only procedure descriptions matching the schema and
1401: * procedure name criteria are returned. They are ordered by
1402: * PROCEDURE_SCHEM, and PROCEDURE_NAME.
1403: *
1404: * <P>Each procedure description has the the following columns:
1405: * <OL>
1406: * <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1407: * <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1408: * <LI><B>PROCEDURE_NAME</B> String => procedure name
1409: * <LI> reserved for future use
1410: * <LI> reserved for future use
1411: * <LI> reserved for future use
1412: * <LI><B>REMARKS</B> String => explanatory comment on the procedure
1413: * <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
1414: * <UL>
1415: * <LI> procedureResultUnknown - May return a result
1416: * <LI> procedureNoResult - Does not return a result
1417: * <LI> procedureReturnsResult - Returns a result
1418: * </UL>
1419: * <LI><B>SPECIFIC_NAME</B> String => The name which uniquely
1420: * identifies this procedure within its schema (since JDBC 4.0)
1421: * </OL>
1422: *
1423: * @param catalog a catalog name; "" retrieves those without a
1424: * catalog; null means drop catalog name from the selection criteria
1425: * @param schemaPattern a schema name pattern; "" retrieves those
1426: * without a schema
1427: * @param procedureNamePattern a procedure name pattern
1428: * @return ResultSet - each row is a procedure description
1429: * @see #getSearchStringEscape
1430: * @exception SQLException thrown on failure.
1431: */
1432: public ResultSet getProcedures(String catalog,
1433: String schemaPattern, String procedureNamePattern)
1434: throws SQLException {
1435:
1436: // Using the new JDBC 4.0 version of the query here. The query
1437: // was given a new name to allow the old query to
1438: // be used by ODBCMetaDataGenerator.
1439: return doGetProcs(catalog, schemaPattern, procedureNamePattern,
1440: "getProcedures40");
1441: }
1442:
1443: /**
1444: * Get a description of stored procedures available in a
1445: * catalog. Same as getProcedures() above, except that
1446: * the result set will conform to ODBC specifications.
1447: */
1448: public ResultSet getProceduresForODBC(String catalog,
1449: String schemaPattern, String procedureNamePattern)
1450: throws SQLException {
1451:
1452: // For ODBC we still use the transformed version of the JDBC
1453: // 3.0 query, (may change in the future).
1454: return doGetProcs(catalog, schemaPattern, procedureNamePattern,
1455: "odbc_getProcedures");
1456: }
1457:
1458: /**
1459: * Implements DatabaseMetaData.getFunctions() for an embedded
1460: * database. Queries the database to get information about
1461: * functions (procedures returning values). Executes the
1462: * 'getFunctions' query from metadata.properties to obtain the
1463: * ResultSet to return.<p> Compatibility: This is a new method in
1464: * the API which is only available with with Derby versions > 10.1 and
1465: * JDK versions >= 1.6 <p>Upgrade: Since this is a new query it
1466: * does not have an SPS, and will be available as soon as any
1467: * database, new or old, is booted with the new version of Derby,
1468: * (in <b>soft and hard</b> upgrade).
1469: * @param catalog limit the search to functions in this catalog
1470: * (not used)
1471: * @param schemaPattern limit the search to functions in schemas
1472: * matching this pattern
1473: * @param functionNamePattern limit the search to functions
1474: * matching this pattern
1475: * @return a ResultSet with metadata information
1476: * @throws SQLException if any of the underlying jdbc methods fail
1477: */
1478: public ResultSet getFunctions(java.lang.String catalog,
1479: java.lang.String schemaPattern,
1480: java.lang.String functionNamePattern) throws SQLException {
1481: return doGetProcs(catalog, schemaPattern, functionNamePattern,
1482: "getFunctions");
1483: }
1484:
1485: /**
1486: * Does the actual work for the getProcedures and getFunctions
1487: * metadata calls. See getProcedures() method above for parameter
1488: * descriptions.
1489: * @param queryName Name of the query to execute; is used
1490: * to determine whether the result set should conform to
1491: * JDBC or ODBC specifications.
1492: */
1493: private ResultSet doGetProcs(String catalog, String schemaPattern,
1494: String procedureNamePattern, String queryName)
1495: throws SQLException {
1496:
1497: PreparedStatement s = getPreparedQuery(queryName);
1498: s.setString(1, swapNull(catalog));
1499: s.setString(2, swapNull(schemaPattern));
1500: s.setString(3, swapNull(procedureNamePattern));
1501: return s.executeQuery();
1502: }
1503:
1504: /**
1505: * Get a description of a catalog's stored procedure parameters
1506: * and result columns.
1507: *
1508: * <P>Only descriptions matching the schema, procedure and
1509: * parameter name criteria are returned. They are ordered by
1510: * PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
1511: * if any, is first. Next are the parameter descriptions in call
1512: * order. The column descriptions follow in column number order.
1513: *
1514: * <P>Each row in the ResultSet is a parameter description or
1515: * column description with the following fields:
1516: * <OL>
1517: * <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
1518: * <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
1519: * <LI><B>PROCEDURE_NAME</B> String => procedure name
1520: * <LI><B>COLUMN_NAME</B> String => column/parameter name
1521: * <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
1522: * <UL>
1523: * <LI> procedureColumnUnknown - nobody knows
1524: * <LI> procedureColumnIn - IN parameter
1525: * <LI> procedureColumnInOut - INOUT parameter
1526: * <LI> procedureColumnOut - OUT parameter
1527: * <LI> procedureColumnReturn - procedure return value
1528: * <LI> procedureColumnResult - result column in ResultSet
1529: * </UL>
1530: * <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
1531: * <LI><B>TYPE_NAME</B> String => SQL type name
1532: * <LI><B>PRECISION</B> int => precision
1533: * <LI><B>LENGTH</B> int => length in bytes of data
1534: * <LI><B>SCALE</B> short => scale
1535: * <LI><B>RADIX</B> short => radix
1536: * <LI><B>NULLABLE</B> short => can it contain NULL?
1537: * <UL>
1538: * <LI> procedureNoNulls - does not allow NULL values
1539: * <LI> procedureNullable - allows NULL values
1540: * <LI> procedureNullableUnknown - nullability unknown
1541: * </UL>
1542: * <LI><B>REMARKS</B> String => comment describing parameter/column
1543: * <LI><B>COLUMN_DEF</B> String
1544: * <LI><B>SQL_DATA_TYPE</B> int
1545: * <LI><B>SQL_DATETIME_SUB</B> int
1546: * <LI><B>CHAR_OCTET_LENGTH</B> int
1547: * <LI><B>ORDINAL_POSITION</B> int
1548: * <LI><B>IS_NULLABLE</B> String
1549: * <LI><B>SPECIFIC_NAME</B> String
1550: * </OL>
1551: *
1552: * <P><B>Note:</B> Some databases may not return the column
1553: * descriptions for a procedure. Additional columns beyond
1554: * SPECIFIC_NAME can be defined by the database.
1555: *
1556: * @param catalog a catalog name; "" retrieves those without a
1557: * catalog; null means drop catalog name from the selection criteria
1558: * @param schemaPattern a schema name pattern; "" retrieves those
1559: * without a schema
1560: * @param procedureNamePattern a procedure name pattern
1561: * @param columnNamePattern a column name pattern
1562: * @return ResultSet - each row is a stored procedure parameter or
1563: * column description
1564: * @see #getSearchStringEscape
1565: * @exception SQLException thrown on failure.
1566: */
1567: public ResultSet getProcedureColumns(String catalog,
1568: String schemaPattern, String procedureNamePattern,
1569: String columnNamePattern) throws SQLException {
1570:
1571: // Using the new JDBC 4.0 version of the query here. The query
1572: // was given a new name to allow the old query to
1573: // be used by ODBCMetaDataGenerator.
1574: return doGetProcCols(catalog, schemaPattern,
1575: procedureNamePattern, columnNamePattern,
1576: "getProcedureColumns40");
1577: }
1578:
1579: /**
1580: * Get a description of a catalog's stored procedure parameters
1581: * and result columns. Same as getProcedureColumns() above,
1582: * except that the result set will conform to ODBC specifications.
1583: */
1584: public ResultSet getProcedureColumnsForODBC(String catalog,
1585: String schemaPattern, String procedureNamePattern,
1586: String columnNamePattern) throws SQLException {
1587:
1588: // For ODBC we still use the transformed version of the JDBC
1589: // 3.0 query, (may change in the future).
1590: return doGetProcCols(catalog, schemaPattern,
1591: procedureNamePattern, columnNamePattern,
1592: "odbc_getProcedureColumns");
1593: }
1594:
1595: /**
1596: * Implements DatabaseMetaData.getFunctionColumns() for an embedded
1597: * database. Queries the database to get information about
1598: * function parameters. Executes the
1599: * 'getFunctionColumns' query from metadata.properties to obtain the
1600: * ResultSet.<p> Compatibility: This is a new method in
1601: * the API which is only available with with Derby versions > 10.1 and
1602: * JDK versions >= 1.6 <p>Upgrade: Since this is a new query it
1603: * does not have an SPS, and will be available as soon as any
1604: * database, new or old, is booted with the new version of Derby,
1605: * (in <b>soft and hard</b> upgrade).
1606: * @param catalog limit the search to functions in this catalog
1607: * (not used)
1608: * @param schemaPattern limit the search to functions in schemas
1609: * matching this pattern
1610: * @param functionNamePattern limit the search to functions
1611: * matching this pattern
1612: * @param parameterNamePattern limit the search parameters
1613: * matching this pattern
1614: * @return a ResultSet with metadata information
1615: * @throws SQLException if a database error occurs
1616: */
1617: public ResultSet getFunctionColumns(String catalog,
1618: String schemaPattern, String functionNamePattern,
1619: String parameterNamePattern) throws SQLException {
1620: PreparedStatement s = getPreparedQuery("getFunctionColumns");
1621:
1622: // Cannot use doGetProcCols() because our query requires
1623: // parameterNamePattern twice, because both LIKE and = is
1624: // required to select parameters with an empty parameter
1625: // name. That is, WHERE paramName LIKE ? will not match an
1626: // empty paramName, but WHERE paramName LIKE ? OR paramName =
1627: // ? will.
1628: s.setString(1, swapNull(schemaPattern));
1629: s.setString(2, swapNull(functionNamePattern));
1630: s.setString(3, swapNull(parameterNamePattern));
1631: s.setString(4, swapNull(parameterNamePattern));
1632: return s.executeQuery();
1633: }
1634:
1635: /**
1636: * Does the actual work for the getProcedureColumns metadata
1637: * calls. See getProcedureColumns() method above for parameter
1638: * descriptions.
1639: * @param queryName Name of the query to execute; is used
1640: * to determine whether the result set should conform to
1641: * JDBC or ODBC specifications.
1642: */
1643: private ResultSet doGetProcCols(String catalog,
1644: String schemaPattern, String procedureNamePattern,
1645: String columnNamePattern, String queryName)
1646: throws SQLException {
1647:
1648: PreparedStatement s = getPreparedQuery(queryName);
1649: //
1650: // catalog is not part of the query
1651: //
1652: s.setString(1, swapNull(schemaPattern));
1653: s.setString(2, swapNull(procedureNamePattern));
1654: s.setString(3, swapNull(columnNamePattern));
1655: return s.executeQuery();
1656: }
1657:
1658: /**
1659: * Get a description of tables available in a catalog.
1660: *
1661: * <P>Only table descriptions matching the catalog, schema, table
1662: * name and type criteria are returned. They are ordered by
1663: * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
1664: *
1665: * <P>Each table description has the following columns:
1666: * <OL>
1667: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1668: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1669: * <LI><B>TABLE_NAME</B> String => table name
1670: * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1671: * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1672: * "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1673: * <LI><B>REMARKS</B> String => explanatory comment on the table
1674: * <LI><B>TYPE_CAT</B> String => the types catalog (may be
1675: * <code>null</code>)
1676: * <LI><B>TYPE_SCHEM</B> String => the types schema (may be
1677: * <code>null</code>)
1678: * <LI><B>TYPE_NAME</B> String => type name (may be
1679: * <code>null</code>)
1680: * <LI><B>SELF_REFERENCING_COL_NAME</B> String => name of the
1681: * designated "identifier" column of a typed table (may
1682: * be <code>null</code>)
1683: * <LI><B>REF_GENERATION</B> String => specifies how values in
1684: * SELF_REFERENCING_COL_NAME are created. Values are
1685: * "SYSTEM", "USER", "DERIVED". (may be
1686: * <code>null</code>)
1687: * </OL>
1688: *
1689: * <P><B>Note:</B> Some databases may not return information for
1690: * all tables.
1691: *
1692: * @param catalog a catalog name; "" retrieves those without a
1693: * catalog; null means drop catalog name from the selection criteria
1694: * @param schemaPattern a schema name pattern; "" retrieves those
1695: * without a schema
1696: * @param tableNamePattern a table name pattern
1697: * @param types a list of table types to include; null returns all types
1698: * @return ResultSet - each row is a table description
1699: * @see #getSearchStringEscape
1700: * @exception SQLException thrown on failure.
1701: */
1702: public ResultSet getTables(String catalog, String schemaPattern,
1703: String tableNamePattern, String types[])
1704: throws SQLException {
1705: synchronized (getConnectionSynchronization()) {
1706: setupContextStack();
1707: ResultSet rs = null;
1708: try {
1709:
1710: String queryText = getQueryDescriptions(false)
1711: .getProperty("getTables");
1712:
1713: /*
1714: * The query text is assumed to end with a "where" clause, so
1715: * that we can safely append
1716: * "and table_Type in ('xxx','yyy','zzz', ...)" and
1717: * have it become part of the where clause.
1718: *
1719: * Let's assume for now that the table type first char corresponds
1720: * to JBMS table type identifiers.
1721: */
1722: StringBuffer whereClauseTail = new StringBuffer(
1723: queryText);
1724:
1725: if (types != null && types.length >= 1) {
1726: whereClauseTail.append(" AND TABLETYPE IN ('");
1727: whereClauseTail.append(types[0].substring(0, 1));
1728:
1729: for (int i = 1; i < types.length; i++) {
1730: whereClauseTail.append("','");
1731: whereClauseTail
1732: .append(types[i].substring(0, 1));
1733: }
1734: whereClauseTail.append("')");
1735: }
1736: // Add the order by clause after the 'in' list.
1737: whereClauseTail
1738: .append(" ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME");
1739:
1740: PreparedStatement s = getEmbedConnection()
1741: .prepareMetaDataStatement(
1742: whereClauseTail.toString());
1743:
1744: s.setString(1, swapNull(catalog));
1745: s.setString(2, swapNull(schemaPattern));
1746: s.setString(3, swapNull(tableNamePattern));
1747:
1748: rs = s.executeQuery();
1749: } catch (Throwable t) {
1750: throw handleException(t);
1751: } finally {
1752: restoreContextStack();
1753: }
1754:
1755: return rs;
1756: }
1757: }
1758:
1759: /**
1760: * Get the schema names available in this database. The results
1761: * are ordered by schema name.
1762: *
1763: * <P>The schema columns are:
1764: * <OL>
1765: * <li><strong>TABLE_SCHEM</strong> String => schema name</li>
1766: * <li><strong>TABLE_CATALOG</strong> String => catalog name
1767: * (may be <code>null</code>)</li>
1768: * </OL>
1769: *
1770: * @return ResultSet - each row is a schema description
1771: * @exception SQLException thrown on failure.
1772: */
1773: public ResultSet getSchemas() throws SQLException {
1774: return getSchemas(null, null);
1775: }
1776:
1777: /**
1778: * Get the catalog names available in this database. The results
1779: * are ordered by catalog name.
1780: *
1781: * <P>The catalog column is:
1782: * <OL>
1783: * <LI><B>TABLE_CAT</B> String => catalog name
1784: * </OL>
1785: *
1786: * @return ResultSet - each row has a single String column that is a
1787: * catalog name
1788: * @exception SQLException thrown on failure.
1789: */
1790: public ResultSet getCatalogs() throws SQLException {
1791: return getSimpleQuery("getCatalogs");
1792: }
1793:
1794: /**
1795: * Get the table types available in this database. The results
1796: * are ordered by table type.
1797: *
1798: * <P>The table type is:
1799: * <OL>
1800: * <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
1801: * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
1802: * "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
1803: * </OL>
1804: *
1805: * @return ResultSet - each row has a single String column that is a
1806: * table type
1807: * @exception SQLException thrown on failure.
1808: */
1809: public ResultSet getTableTypes() throws SQLException {
1810: return getSimpleQuery("getTableTypes");
1811: }
1812:
1813: /**
1814: * Get a description of table columns available in a catalog.
1815: *
1816: * <P>Only column descriptions matching the catalog, schema, table
1817: * and column name criteria are returned. They are ordered by
1818: * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
1819: *
1820: * <P>Each column description has the following columns:
1821: * <OL>
1822: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1823: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1824: * <LI><B>TABLE_NAME</B> String => table name
1825: * <LI><B>COLUMN_NAME</B> String => column name
1826: * <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
1827: * <LI><B>TYPE_NAME</B> String => Data source dependent type name
1828: * <LI><B>COLUMN_SIZE</B> int => column size. For char or date
1829: * types this is the maximum number of characters, for numeric or
1830: * decimal types this is precision.
1831: * <LI><B>BUFFER_LENGTH</B> is not used.
1832: * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
1833: * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
1834: * <LI><B>NULLABLE</B> int => is NULL allowed?
1835: * <UL>
1836: * <LI> columnNoNulls - might not allow NULL values
1837: * <LI> columnNullable - definitely allows NULL values
1838: * <LI> columnNullableUnknown - nullability unknown
1839: * </UL>
1840: * <LI><B>REMARKS</B> String => comment describing column (may be null)
1841: * <LI><B>COLUMN_DEF</B> String => default value (may be null)
1842: * <LI><B>SQL_DATA_TYPE</B> int => unused
1843: * <LI><B>SQL_DATETIME_SUB</B> int => unused
1844: * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
1845: * maximum number of bytes in the column
1846: * <LI><B>ORDINAL_POSITION</B> int => index of column in table
1847: * (starting at 1)
1848: * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
1849: * does not allow NULL values; "YES" means the column might
1850: * allow NULL values. An empty string means nobody knows.
1851: * <LI><B>SCOPE_CATLOG</B> String => catalog of table that is the
1852: * scope of a reference attribute (<code>null</code> if DATA_TYPE
1853: * isn't REF)
1854: * <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the
1855: * scope of a reference attribute (<code>null</code> if the
1856: * DATA_TYPE isn't REF)
1857: * <LI><B>SCOPE_TABLE</B> String => table name that this the
1858: * scope of a reference attribure (<code>null</code> if the
1859: * DATA_TYPE isn't REF)
1860: * <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct
1861: * type or user-generated Ref type, SQL type from java.sql.Types
1862: * (<code>null</code> if DATA_TYPE isn't DISTINCT or
1863: * user-generated REF)
1864: * <LI><B>IS_AUTOINCREMENT</B> String => Indicates whether this
1865: * column is auto incremented
1866: * <UL>
1867: * <LI> YES --- if the column is auto incremented
1868: * <LI> NO --- if the column is not auto incremented
1869: * <LI> empty string --- if it cannot be determined whether the
1870: * column is auto incremented parameter is unknown
1871: * </UL>
1872: * </OL>
1873: *
1874: * @param catalog a catalog name; "" retrieves those without a
1875: * catalog; null means drop catalog name from the selection criteria
1876: * @param schemaPattern a schema name pattern; "" retrieves those
1877: * without a schema
1878: * @param tableNamePattern a table name pattern
1879: * @param columnNamePattern a column name pattern
1880: * @return ResultSet - each row is a column description
1881: * @see #getSearchStringEscape
1882: * @exception SQLException thrown on failure.
1883: */
1884: public ResultSet getColumns(String catalog, String schemaPattern,
1885: String tableNamePattern, String columnNamePattern)
1886: throws SQLException {
1887:
1888: return doGetCols(catalog, schemaPattern, tableNamePattern,
1889: columnNamePattern, "getColumns");
1890: }
1891:
1892: /**
1893: * Get a description of table columns available in a catalog.
1894: * Same as getColumns() above, except that the result set
1895: * will conform to ODBC specifications.
1896: */
1897: public ResultSet getColumnsForODBC(String catalog,
1898: String schemaPattern, String tableNamePattern,
1899: String columnNamePattern) throws SQLException {
1900:
1901: return doGetCols(catalog, schemaPattern, tableNamePattern,
1902: columnNamePattern, "odbc_getColumns");
1903: }
1904:
1905: /**
1906: * Does the actual work for the getColumns metadata calls.
1907: * See getColumns() method above for parameter descriptions.
1908: * @param queryName Name of the query to execute; is used
1909: * to determine whether the result set should conform to
1910: * JDBC or ODBC specifications.
1911: */
1912: private ResultSet doGetCols(String catalog, String schemaPattern,
1913: String tableNamePattern, String columnNamePattern,
1914: String queryName) throws SQLException {
1915:
1916: PreparedStatement s = getPreparedQuery(queryName);
1917: s.setString(1, swapNull(catalog));
1918: s.setString(2, swapNull(schemaPattern));
1919: s.setString(3, swapNull(tableNamePattern));
1920: s.setString(4, swapNull(columnNamePattern));
1921: return s.executeQuery();
1922: }
1923:
1924: /**
1925: * Get a description of the access rights for a table's columns.
1926: *
1927: * <P>Only privileges matching the column name criteria are
1928: * returned. They are ordered by COLUMN_NAME and PRIVILEGE.
1929: *
1930: * <P>Each privilige description has the following columns:
1931: * <OL>
1932: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1933: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1934: * <LI><B>TABLE_NAME</B> String => table name
1935: * <LI><B>COLUMN_NAME</B> String => column name
1936: * <LI><B>GRANTOR</B> => grantor of access (may be null)
1937: * <LI><B>GRANTEE</B> String => grantee of access
1938: * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1939: * INSERT, UPDATE, REFRENCES, ...)
1940: * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1941: * to grant to others; "NO" if not; null if unknown
1942: * </OL>
1943: *
1944: * @param catalog a catalog name; "" retrieves those without a
1945: * catalog; null means drop catalog name from the selection criteria
1946: * @param schema a schema name; "" retrieves those without a schema
1947: * @param table a table name
1948: * @param columnNamePattern a column name pattern
1949: * @return ResultSet - each row is a column privilege description
1950: * @see #getSearchStringEscape
1951: * @exception SQLException thrown on failure.
1952: */
1953: public ResultSet getColumnPrivileges(String catalog, String schema,
1954: String table, String columnNamePattern) throws SQLException {
1955: PreparedStatement s = getPreparedQuery("getColumnPrivileges");
1956: s.setString(1, swapNull(catalog));
1957: s.setString(2, swapNull(schema));
1958: s.setString(3, swapNull(table));
1959: s.setString(4, swapNull(columnNamePattern));
1960: return s.executeQuery();
1961: }
1962:
1963: /**
1964: * Get a description of the access rights for each table available
1965: * in a catalog. Note that a table privilege applies to one or
1966: * more columns in the table. It would be wrong to assume that
1967: * this priviledge applies to all columns (this may be true for
1968: * some systems but is not true for all.)
1969: *
1970: * <P>Only privileges matching the schema and table name
1971: * criteria are returned. They are ordered by TABLE_SCHEM,
1972: * TABLE_NAME, and PRIVILEGE.
1973: *
1974: * <P>Each privilige description has the following columns:
1975: * <OL>
1976: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
1977: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
1978: * <LI><B>TABLE_NAME</B> String => table name
1979: * <LI><B>GRANTOR</B> => grantor of access (may be null)
1980: * <LI><B>GRANTEE</B> String => grantee of access
1981: * <LI><B>PRIVILEGE</B> String => name of access (SELECT,
1982: * INSERT, UPDATE, REFRENCES, ...)
1983: * <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
1984: * to grant to others; "NO" if not; null if unknown
1985: * </OL>
1986: *
1987: * @param catalog a catalog name; "" retrieves those without a
1988: * catalog; null means drop catalog name from the selection criteria
1989: * @param schemaPattern a schema name pattern; "" retrieves those
1990: * without a schema
1991: * @param tableNamePattern a table name pattern
1992: * @return ResultSet - each row is a table privilege description
1993: * @see #getSearchStringEscape
1994: * @exception SQLException thrown on failure.
1995: */
1996: public ResultSet getTablePrivileges(String catalog,
1997: String schemaPattern, String tableNamePattern)
1998: throws SQLException {
1999: PreparedStatement s = getPreparedQuery("getTablePrivileges");
2000: s.setString(1, swapNull(catalog));
2001: s.setString(2, swapNull(schemaPattern));
2002: s.setString(3, swapNull(tableNamePattern));
2003: return s.executeQuery();
2004: }
2005:
2006: /**
2007: * Get a description of a table's optimal set of columns that
2008: * uniquely identifies a row. They are ordered by SCOPE.
2009: *
2010: * <P>Each column description has the following columns:
2011: * <OL>
2012: * <LI><B>SCOPE</B> short => actual scope of result
2013: * <UL>
2014: * <LI> bestRowTemporary - very temporary, while using row
2015: * <LI> bestRowTransaction - valid for remainder of current transaction
2016: * <LI> bestRowSession - valid for remainder of current session
2017: * </UL>
2018: * <LI><B>COLUMN_NAME</B> String => column name
2019: * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types
2020: * <LI><B>TYPE_NAME</B> String => Data source dependent type name
2021: * <LI><B>COLUMN_SIZE</B> int => precision
2022: * <LI><B>BUFFER_LENGTH</B> int => not used
2023: * <LI><B>DECIMAL_DIGITS</B> short => scale
2024: * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2025: * like an Oracle ROWID
2026: * <UL>
2027: * <LI> bestRowUnknown - may or may not be pseudo column
2028: * <LI> bestRowNotPseudo - is NOT a pseudo column
2029: * <LI> bestRowPseudo - is a pseudo column
2030: * </UL>
2031: * </OL>
2032: *
2033: * @param catalogPattern a catalog name; "" retrieves those without a
2034: * catalog; null means drop catalog name from the selection criteria
2035: * @param schemaPattern a schema name; "" retrieves those without a schema
2036: * @param tablePattern a table name
2037: * @param scope the scope of interest; use same values as SCOPE
2038: * @param nullable include columns that are nullable?
2039: * @return ResultSet - each row is a column description
2040: * @exception SQLException thrown on failure.
2041: */
2042: public ResultSet getBestRowIdentifier(String catalogPattern,
2043: String schemaPattern, String tablePattern, int scope,
2044: boolean nullable) throws SQLException {
2045: return doGetBestRowId(catalogPattern, schemaPattern,
2046: tablePattern, scope, nullable, "");
2047: }
2048:
2049: /**
2050: * Get a description of a table's optimal set of columns that
2051: * uniquely identifies a row. They are ordered by SCOPE.
2052: * Same as getBestRowIdentifier() above, except that the result
2053: * set will conform to ODBC specifications.
2054: */
2055: public ResultSet getBestRowIdentifierForODBC(String catalogPattern,
2056: String schemaPattern, String tablePattern, int scope,
2057: boolean nullable) throws SQLException {
2058:
2059: return doGetBestRowId(catalogPattern, schemaPattern,
2060: tablePattern, scope, nullable, "odbc_");
2061: }
2062:
2063: /**
2064: * Does the actual work for the getBestRowIdentifier metadata
2065: * calls. See getBestRowIdentifier() method above for parameter
2066: * descriptions.
2067: * @param queryPrefix Prefix to be appended to the names of
2068: * the queries used in this method. This is used
2069: * to determine whether the result set should conform to
2070: * JDBC or ODBC specifications.
2071: */
2072: private ResultSet doGetBestRowId(String catalogPattern,
2073: String schemaPattern, String tablePattern, int scope,
2074: boolean nullable, String queryPrefix) throws SQLException {
2075:
2076: int nullableInIntForm = 0;
2077: if (nullable)
2078: nullableInIntForm = 1;
2079:
2080: if (catalogPattern == null) {
2081: catalogPattern = "%";
2082: }
2083: if (schemaPattern == null) {
2084: schemaPattern = "%";
2085: }
2086: if (tablePattern == null) {
2087: tablePattern = "%";
2088: }
2089:
2090: PreparedStatement ps;
2091: boolean done;
2092:
2093: // scope value is bad, return an empty result
2094: if (scope < 0 || scope > 2) {
2095: ps = getPreparedQuery("getBestRowIdentifierEmpty");
2096: return ps.executeQuery();
2097: }
2098:
2099: // see if there is a primary key, use it.
2100: ps = getPreparedQuery("getBestRowIdentifierPrimaryKey");
2101: ps.setString(1, catalogPattern);
2102: ps.setString(2, schemaPattern);
2103: ps.setString(3, tablePattern);
2104:
2105: ResultSet rs = ps.executeQuery();
2106: done = rs.next();
2107: String constraintId = "";
2108: if (done) {
2109: constraintId = rs.getString(1);
2110: }
2111:
2112: rs.close();
2113: ps.close();
2114:
2115: if (done) {
2116: // this one's it, do the real thing and return it.
2117: // we don't need to check catalog, schema, table name
2118: // or scope again.
2119: ps = getPreparedQuery(queryPrefix
2120: + "getBestRowIdentifierPrimaryKeyColumns");
2121: ps.setString(1, constraintId);
2122: ps.setString(2, constraintId);
2123: // note, primary key columns aren't nullable,
2124: // so we skip the nullOk parameter.
2125: return ps.executeQuery();
2126: }
2127:
2128: // get the unique constraint with the fewest columns.
2129: ps = getPreparedQuery("getBestRowIdentifierUniqueConstraint");
2130: ps.setString(1, catalogPattern);
2131: ps.setString(2, schemaPattern);
2132: ps.setString(3, tablePattern);
2133:
2134: rs = ps.executeQuery();
2135: done = rs.next();
2136: if (done) {
2137: constraintId = rs.getString(1);
2138: }
2139: // REMIND: we need to actually check for null columns
2140: // and toss out constraints with null columns if they aren't
2141: // desired... recode this as a WHILE returning at the
2142: // first match or falling off the end.
2143:
2144: rs.close();
2145: ps.close();
2146: if (done) {
2147: // this one's it, do the real thing and return it.
2148: ps = getPreparedQuery(queryPrefix
2149: + "getBestRowIdentifierUniqueKeyColumns");
2150: ps.setString(1, constraintId);
2151: ps.setString(2, constraintId);
2152: ps.setInt(3, nullableInIntForm);
2153: return ps.executeQuery();
2154: }
2155:
2156: // second-to last try -- unique index with minimal # columns
2157: // (only non null columns if so required)
2158: ps = getPreparedQuery("getBestRowIdentifierUniqueIndex");
2159: ps.setString(1, catalogPattern);
2160: ps.setString(2, schemaPattern);
2161: ps.setString(3, tablePattern);
2162:
2163: rs = ps.executeQuery();
2164: done = rs.next();
2165: long indexNum = 0;
2166: if (done) {
2167: indexNum = rs.getLong(1);
2168: }
2169: // REMIND: we need to actually check for null columns
2170: // and toss out constraints with null columns if they aren't
2171: // desired... recode this as a WHILE returning at the
2172: // first match or falling off the end.
2173:
2174: rs.close();
2175: ps.close();
2176: if (done) {
2177: // this one's it, do the real thing and return it.
2178: ps = getPreparedQuery(queryPrefix
2179: + "getBestRowIdentifierUniqueIndexColumns");
2180: ps.setLong(1, indexNum);
2181: ps.setInt(2, nullableInIntForm);
2182: return ps.executeQuery();
2183: }
2184:
2185: // last try -- just return all columns of the table
2186: // the not null ones if that restriction is upon us.
2187: ps = getPreparedQuery(queryPrefix
2188: + "getBestRowIdentifierAllColumns");
2189: ps.setString(1, catalogPattern);
2190: ps.setString(2, schemaPattern);
2191: ps.setString(3, tablePattern);
2192: ps.setInt(4, scope);
2193: ps.setInt(5, nullableInIntForm);
2194: return ps.executeQuery();
2195: }
2196:
2197: /**
2198: * Get a description of a table's columns that are automatically
2199: * updated when any value in a row is updated. They are
2200: * unordered.
2201: *
2202: * <P>Each column description has the following columns:
2203: * <OL>
2204: * <LI><B>SCOPE</B> short => is not used
2205: * <LI><B>COLUMN_NAME</B> String => column name
2206: * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types
2207: * <LI><B>TYPE_NAME</B> String => Data source dependent type name
2208: * <LI><B>COLUMN_SIZE</B> int => precision
2209: * <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
2210: * <LI><B>DECIMAL_DIGITS</B> short => scale
2211: * <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
2212: * like an Oracle ROWID
2213: * <UL>
2214: * <LI> versionColumnUnknown - may or may not be pseudo column
2215: * <LI> versionColumnNotPseudo - is NOT a pseudo column
2216: * <LI> versionColumnPseudo - is a pseudo column
2217: * </UL>
2218: * </OL>
2219: *
2220: * @param catalog a catalog name; "" retrieves those without a
2221: * catalog; null means drop catalog name from the selection criteria
2222: * @param schema a schema name; "" retrieves those without a schema
2223: * @param table a table name
2224: * @return ResultSet - each row is a column description
2225: * @exception SQLException thrown on failure.
2226: */
2227: public ResultSet getVersionColumns(String catalog, String schema,
2228: String table) throws SQLException {
2229: return doGetVersionCols(catalog, schema, table,
2230: "getVersionColumns");
2231: }
2232:
2233: /**
2234: * Get a description of a table's columns that are automatically
2235: * updated when any value in a row is updated. They are
2236: * unordered. Same as getVersionColumns() above, except that
2237: * the result set will conform to ODBC specifications.
2238: */
2239: public ResultSet getVersionColumnsForODBC(String catalog,
2240: String schema, String table) throws SQLException {
2241: return doGetVersionCols(catalog, schema, table,
2242: "odbc_getVersionColumns");
2243: }
2244:
2245: /**
2246: * Does the actual work for the getVersionColumns metadata
2247: * calls. See getVersionColumns() method above for parameter
2248: * descriptions.
2249: * @param queryName Name of the query to execute; is used
2250: * to determine whether the result set should conform to
2251: * JDBC or ODBC specifications.
2252: */
2253: private ResultSet doGetVersionCols(String catalog, String schema,
2254: String table, String queryName) throws SQLException {
2255:
2256: PreparedStatement s = getPreparedQuery(queryName);
2257: s.setString(1, swapNull(catalog));
2258: s.setString(2, swapNull(schema));
2259: s.setString(3, swapNull(table));
2260: return s.executeQuery();
2261: }
2262:
2263: /**
2264: * check if the dictionary is at the same version as the engine. If not,
2265: * then that means stored versions of the JDBC database metadata queries
2266: * may not be compatible with this version of the software.
2267: * This can happen if we are in soft upgrade mode. Since in soft upgrade
2268: * mode, we can't change these stored metadata queries in a backward
2269: * incompatible way, engine needs to read the metadata sql from
2270: * metadata.properties or metadata_net.properties file rather than
2271: * rely on system tables.
2272: *
2273: * @return true if we are not in soft upgrade mode
2274: * @throws SQLException
2275: */
2276: private boolean notInSoftUpgradeMode() throws SQLException {
2277: if (getEmbedConnection().isClosed())
2278: throw Util.noCurrentConnection();
2279:
2280: boolean notInSoftUpgradeMode;
2281: try {
2282: notInSoftUpgradeMode = getLanguageConnectionContext()
2283: .getDataDictionary().checkVersion(
2284: DataDictionary.DD_VERSION_CURRENT, null);
2285: } catch (Throwable t) {
2286: throw handleException(t);
2287: }
2288: return notInSoftUpgradeMode;
2289: }
2290:
2291: /**
2292: * Get a description of a table's primary key columns. They
2293: * are ordered by COLUMN_NAME.
2294: *
2295: * <P>Each primary key column description has the following columns:
2296: * <OL>
2297: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2298: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2299: * <LI><B>TABLE_NAME</B> String => table name
2300: * <LI><B>COLUMN_NAME</B> String => column name
2301: * <LI><B>KEY_SEQ</B> short => sequence number within primary key
2302: * <LI><B>PK_NAME</B> String => primary key name (may be null)
2303: * </OL>
2304: *
2305: * @param catalog a catalog name; "" retrieves those without a
2306: * catalog; null means drop catalog name from the selection criteria
2307: * @param schema a schema name pattern; "" retrieves those
2308: * without a schema
2309: * @param table a table name
2310: * @return ResultSet - each row is a primary key column description
2311: * @exception SQLException thrown on failure.
2312: */
2313: public ResultSet getPrimaryKeys(String catalog, String schema,
2314: String table) throws SQLException {
2315: PreparedStatement s = getPreparedQuery("getPrimaryKeys");
2316: s.setString(1, swapNull(catalog));
2317: s.setString(2, swapNull(schema));
2318: s.setString(3, swapNull(table));
2319: return s.executeQuery();
2320: }
2321:
2322: /**
2323: * Get a description of the primary key columns that are
2324: * referenced by a table's foreign key columns (the primary keys
2325: * imported by a table). They are ordered by PKTABLE_CAT,
2326: * PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
2327: *
2328: * <P>Each primary key column description has the following columns:
2329: * <OL>
2330: * <LI><B>PKTABLE_CAT</B> String => primary key table catalog
2331: * being imported (may be null)
2332: * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
2333: * being imported (may be null)
2334: * <LI><B>PKTABLE_NAME</B> String => primary key table name
2335: * being imported
2336: * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2337: * being imported
2338: * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2339: * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2340: * <LI><B>FKTABLE_NAME</B> String => foreign key table name
2341: * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2342: * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2343: * <LI><B>UPDATE_RULE</B> short => What happens to
2344: * foreign key when primary is updated:
2345: * <UL>
2346: * <LI> importedNoAction - do not allow update of primary
2347: * key if it has been imported
2348: * <LI> importedKeyCascade - change imported key to agree
2349: * with primary key update
2350: * <LI> importedKeySetNull - change imported key to NULL if
2351: * its primary key has been updated
2352: * <LI> importedKeySetDefault - change imported key to default values
2353: * if its primary key has been updated
2354: * <LI> importedKeyRestrict - same as importedKeyNoAction
2355: * (for ODBC 2.x compatibility)
2356: * </UL>
2357: * <LI><B>DELETE_RULE</B> short => What happens to
2358: * the foreign key when primary is deleted.
2359: * <UL>
2360: * <LI> importedKeyNoAction - do not allow delete of primary
2361: * key if it has been imported
2362: * <LI> importedKeyCascade - delete rows that import a deleted key
2363: * <LI> importedKeySetNull - change imported key to NULL if
2364: * its primary key has been deleted
2365: * <LI> importedKeyRestrict - same as importedKeyNoAction
2366: * (for ODBC 2.x compatibility)
2367: * <LI> importedKeySetDefault - change imported key to default if
2368: * its primary key has been deleted
2369: * </UL>
2370: * <LI><B>FK_NAME</B> String => foreign key name (may be null)
2371: * <LI><B>PK_NAME</B> String => primary key name (may be null)
2372: * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
2373: * constraints be deferred until commit
2374: * <UL>
2375: * <LI> importedKeyInitiallyDeferred - see SQL92 for definition
2376: * <LI> importedKeyInitiallyImmediate - see SQL92 for definition
2377: * <LI> importedKeyNotDeferrable - see SQL92 for definition
2378: * </UL>
2379: * </OL>
2380: *
2381: * @param catalog a catalog name; "" retrieves those without a
2382: * catalog; null means drop catalog name from the selection criteria
2383: * @param schema a schema name pattern; "" retrieves those
2384: * without a schema
2385: * @param table a table name
2386: * @return ResultSet - each row is a primary key column description
2387: * @see #getExportedKeys
2388: * @exception SQLException thrown on failure.
2389: */
2390: public ResultSet getImportedKeys(String catalog, String schema,
2391: String table) throws SQLException {
2392: PreparedStatement s = getPreparedQuery("getImportedKeys");
2393: s.setString(1, swapNull(catalog));
2394: s.setString(2, swapNull(schema));
2395: s.setString(3, swapNull(table));
2396: return s.executeQuery();
2397: }
2398:
2399: /**
2400: * Get a description of the foreign key columns that reference a
2401: * table's primary key columns (the foreign keys exported by a
2402: * table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
2403: * FKTABLE_NAME, and KEY_SEQ.
2404: *
2405: * <P>Each foreign key column description has the following columns:
2406: * <OL>
2407: * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
2408: * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
2409: * <LI><B>PKTABLE_NAME</B> String => primary key table name
2410: * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2411: * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2412: * being exported (may be null)
2413: * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2414: * being exported (may be null)
2415: * <LI><B>FKTABLE_NAME</B> String => foreign key table name
2416: * being exported
2417: * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2418: * being exported
2419: * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2420: * <LI><B>UPDATE_RULE</B> short => What happens to
2421: * foreign key when primary is updated:
2422: * <UL>
2423: * <LI> importedNoAction - do not allow update of primary
2424: * key if it has been imported
2425: * <LI> importedKeyCascade - change imported key to agree
2426: * with primary key update
2427: * <LI> importedKeySetNull - change imported key to NULL if
2428: * its primary key has been updated
2429: * <LI> importedKeySetDefault - change imported key to default values
2430: * if its primary key has been updated
2431: * <LI> importedKeyRestrict - same as importedKeyNoAction
2432: * (for ODBC 2.x compatibility)
2433: * </UL>
2434: * <LI><B>DELETE_RULE</B> short => What happens to
2435: * the foreign key when primary is deleted.
2436: * <UL>
2437: * <LI> importedKeyNoAction - do not allow delete of primary
2438: * key if it has been imported
2439: * <LI> importedKeyCascade - delete rows that import a deleted key
2440: * <LI> importedKeySetNull - change imported key to NULL if
2441: * its primary key has been deleted
2442: * <LI> importedKeyRestrict - same as importedKeyNoAction
2443: * (for ODBC 2.x compatibility)
2444: * <LI> importedKeySetDefault - change imported key to default if
2445: * its primary key has been deleted
2446: * </UL>
2447: * <LI><B>FK_NAME</B> String => foreign key name (may be null)
2448: * <LI><B>PK_NAME</B> String => primary key name (may be null)
2449: * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
2450: * constraints be deferred until commit
2451: * <UL>
2452: * <LI> importedKeyInitiallyDeferred - see SQL92 for definition
2453: * <LI> importedKeyInitiallyImmediate - see SQL92 for definition
2454: * <LI> importedKeyNotDeferrable - see SQL92 for definition
2455: * </UL>
2456: * </OL>
2457: *
2458: * @param catalog a catalog name; "" retrieves those without a
2459: * catalog; null means drop catalog name from the selection criteria
2460: * @param schema a schema name pattern; "" retrieves those
2461: * without a schema
2462: * @param table a table name
2463: * @return ResultSet - each row is a foreign key column description
2464: * @see #getImportedKeys
2465: * @exception SQLException thrown on failure.
2466: */
2467: public ResultSet getExportedKeys(String catalog, String schema,
2468: String table) throws SQLException {
2469: PreparedStatement s = getPreparedQuery("getCrossReference");
2470: s.setString(1, swapNull(catalog));
2471: s.setString(2, swapNull(schema));
2472: s.setString(3, swapNull(table));
2473: s.setString(4, swapNull(null));
2474: s.setString(5, swapNull(null));
2475: s.setString(6, swapNull(null));
2476: return s.executeQuery();
2477: }
2478:
2479: /**
2480: * Get a description of the foreign key columns in the foreign key
2481: * table that reference the primary key columns of the primary key
2482: * table (describe how one table imports another's key.) This
2483: * should normally return a single foreign key/primary key pair
2484: * (most tables only import a foreign key from a table once.) They
2485: * are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
2486: * KEY_SEQ.
2487: *
2488: * <P>Each foreign key column description has the following columns:
2489: * <OL>
2490: * <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
2491: * <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
2492: * <LI><B>PKTABLE_NAME</B> String => primary key table name
2493: * <LI><B>PKCOLUMN_NAME</B> String => primary key column name
2494: * <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
2495: * being exported (may be null)
2496: * <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
2497: * being exported (may be null)
2498: * <LI><B>FKTABLE_NAME</B> String => foreign key table name
2499: * being exported
2500: * <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
2501: * being exported
2502: * <LI><B>KEY_SEQ</B> short => sequence number within foreign key
2503: * <LI><B>UPDATE_RULE</B> short => What happens to
2504: * foreign key when primary is updated:
2505: * <UL>
2506: * <LI> importedNoAction - do not allow update of primary
2507: * key if it has been imported
2508: * <LI> importedKeyCascade - change imported key to agree
2509: * with primary key update
2510: * <LI> importedKeySetNull - change imported key to NULL if
2511: * its primary key has been updated
2512: * <LI> importedKeySetDefault - change imported key to default values
2513: * if its primary key has been updated
2514: * <LI> importedKeyRestrict - same as importedKeyNoAction
2515: * (for ODBC 2.x compatibility)
2516: * </UL>
2517: * <LI><B>DELETE_RULE</B> short => What happens to
2518: * the foreign key when primary is deleted.
2519: * <UL>
2520: * <LI> importedKeyNoAction - do not allow delete of primary
2521: * key if it has been imported
2522: * <LI> importedKeyCascade - delete rows that import a deleted key
2523: * <LI> importedKeySetNull - change imported key to NULL if
2524: * its primary key has been deleted
2525: * <LI> importedKeyRestrict - same as importedKeyNoAction
2526: * (for ODBC 2.x compatibility)
2527: * <LI> importedKeySetDefault - change imported key to default if
2528: * its primary key has been deleted
2529: * </UL>
2530: * <LI><B>FK_NAME</B> String => foreign key name (may be null)
2531: * <LI><B>PK_NAME</B> String => primary key name (may be null)
2532: * <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
2533: * constraints be deferred until commit
2534: * <UL>
2535: * <LI> importedKeyInitiallyDeferred - see SQL92 for definition
2536: * <LI> importedKeyInitiallyImmediate - see SQL92 for definition
2537: * <LI> importedKeyNotDeferrable - see SQL92 for definition
2538: * </UL>
2539: * </OL>
2540: *
2541: * @param primaryCatalog a catalog name; "" retrieves those without a
2542: * catalog; null means drop catalog name from the selection criteria
2543: * @param primarySchema a schema name pattern; "" retrieves those
2544: * without a schema
2545: * @param primaryTable the table name that exports the key
2546: * @param foreignCatalog a catalog name; "" retrieves those without a
2547: * catalog; null means drop catalog name from the selection criteria
2548: * @param foreignSchema a schema name pattern; "" retrieves those
2549: * without a schema
2550: * @param foreignTable the table name that imports the key
2551: * @return ResultSet - each row is a foreign key column description
2552: * @see #getImportedKeys
2553: * @exception SQLException thrown on failure.
2554: */
2555: public ResultSet getCrossReference(String primaryCatalog,
2556: String primarySchema, String primaryTable,
2557: String foreignCatalog, String foreignSchema,
2558: String foreignTable) throws SQLException {
2559: PreparedStatement s = getPreparedQuery("getCrossReference");
2560: s.setString(1, swapNull(primaryCatalog));
2561: s.setString(2, swapNull(primarySchema));
2562: s.setString(3, swapNull(primaryTable));
2563: s.setString(4, swapNull(foreignCatalog));
2564: s.setString(5, swapNull(foreignSchema));
2565: s.setString(6, swapNull(foreignTable));
2566: return s.executeQuery();
2567: }
2568:
2569: /**
2570: * Get a description of all the standard SQL types supported by
2571: * this database. They are ordered by DATA_TYPE and then by how
2572: * closely the data type maps to the corresponding JDBC SQL type.
2573: *
2574: * <P>Each type description has the following columns:
2575: * <OL>
2576: * <LI><B>TYPE_NAME</B> String => Type name
2577: * <LI><B>DATA_TYPE</B> int => SQL data type from java.sql.Types
2578: * <LI><B>PRECISION</B> int => maximum precision
2579: * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
2580: * (may be null)
2581: * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
2582: (may be null)
2583: * <LI><B>CREATE_PARAMS</B> String => parameters used in creating
2584: * the type (may be null)
2585: * <LI><B>NULLABLE</B> short => can you use NULL for this type?
2586: * <UL>
2587: * <LI> typeNoNulls - does not allow NULL values
2588: * <LI> typeNullable - allows NULL values
2589: * <LI> typeNullableUnknown - nullability unknown
2590: * </UL>
2591: * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
2592: * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
2593: * <UL>
2594: * <LI> typePredNone - No support
2595: * <LI> typePredChar - Only supported with WHERE .. LIKE
2596: * <LI> typePredBasic - Supported except for WHERE .. LIKE
2597: * <LI> typeSearchable - Supported for all WHERE ..
2598: * </UL>
2599: * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
2600: * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
2601: * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
2602: * auto-increment value?
2603: * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
2604: * (may be null)
2605: * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
2606: * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
2607: * <LI><B>SQL_DATA_TYPE</B> int => unused
2608: * <LI><B>SQL_DATETIME_SUB</B> int => unused
2609: * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
2610: * </OL>
2611: *
2612: * @return ResultSet - each row is a SQL type description
2613: * @exception SQLException thrown on failure.
2614: */
2615: public ResultSet getTypeInfo() throws SQLException {
2616: return getSimpleQuery("getTypeInfo");
2617: }
2618:
2619: /**
2620: * Get a description of all the standard SQL types supported by
2621: * this database. They are ordered by DATA_TYPE and then by how
2622: * closely the data type maps to the corresponding JDBC SQL type.
2623: * Same as getTypeInfo above, except that the result set will
2624: * conform to ODBC specifications.
2625: */
2626: public ResultSet getTypeInfoForODBC() throws SQLException {
2627: return getSimpleQuery("odbc_getTypeInfo");
2628: }
2629:
2630: /**
2631: * Get a description of a table's indices and statistics. They are
2632: * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
2633: *
2634: * <P>Each index column description has the following columns:
2635: * <OL>
2636: * <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2637: * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2638: * <LI><B>TABLE_NAME</B> String => table name
2639: * <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
2640: * false when TYPE is tableIndexStatistic
2641: * <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
2642: * null when TYPE is tableIndexStatistic
2643: * <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
2644: * tableIndexStatistic
2645: * <LI><B>TYPE</B> short => index type:
2646: * <UL>
2647: * <LI> tableIndexStatistic - this identifies table statistics that are
2648: * returned in conjuction with a table's index descriptions
2649: * <LI> tableIndexClustered - this is a clustered index
2650: * <LI> tableIndexHashed - this is a hashed index
2651: * <LI> tableIndexOther - this is some other style of index
2652: * </UL>
2653: * <LI><B>ORDINAL_POSITION</B> short => column sequence number
2654: * within index; zero when TYPE is tableIndexStatistic
2655: * <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
2656: * tableIndexStatistic
2657: * <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
2658: * "D" => descending, may be null if sort sequence is not supported;
2659: * null when TYPE is tableIndexStatistic
2660: * <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
2661: * this is the number of rows in the table; otherwise, it is the
2662: * number of unique values in the index.
2663: * <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
2664: * this is the number of pages used for the table, otherwise it
2665: * is the number of pages used for the current index.
2666: * <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
2667: * (may be null)
2668: * </OL>
2669: *
2670: * @param catalog a catalog name; "" retrieves those without a
2671: * catalog; null means drop catalog name from the selection criteria
2672: * @param schema a schema name pattern; "" retrieves those without a schema
2673: * @param table a table name
2674: * @param unique when true, return only indices for unique values;
2675: * when false, return indices regardless of whether unique or not
2676: * @param approximate when true, result is allowed to reflect approximate
2677: * or out of data values; when false, results are requested to be
2678: * accurate
2679: * @return ResultSet - each row is an index column description
2680: * @exception SQLException thrown on failure.
2681: */
2682: public ResultSet getIndexInfo(String catalog, String schema,
2683: String table, boolean unique, boolean approximate)
2684: throws SQLException {
2685: return doGetIndexInfo(catalog, schema, table, unique,
2686: approximate, "getIndexInfo");
2687: }
2688:
2689: /**
2690: * Get a description of a table's indices and statistics. They are
2691: * ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
2692: * Same as getIndexInfo above, except that the result set will
2693: * conform to ODBC specifications.
2694: */
2695: public ResultSet getIndexInfoForODBC(String catalog, String schema,
2696: String table, boolean unique, boolean approximate)
2697: throws SQLException {
2698: return doGetIndexInfo(catalog, schema, table, unique,
2699: approximate, "odbc_getIndexInfo");
2700: }
2701:
2702: /**
2703: * Does the actual work for the getIndexInfo metadata
2704: * calls. See getIndexInfo() method above for parameter
2705: * descriptions.
2706: * @param queryName Name of the query to execute; is used
2707: * to determine whether the result set should conform to
2708: * JDBC or ODBC specifications.
2709: */
2710: private ResultSet doGetIndexInfo(String catalog, String schema,
2711: String table, boolean unique, boolean approximate,
2712: String queryName) throws SQLException {
2713:
2714: int approximateInInt = 0;
2715: if (approximate)
2716: approximateInInt = 1;
2717: PreparedStatement s = getPreparedQuery(queryName);
2718: s.setString(1, swapNull(catalog));
2719: s.setString(2, swapNull(schema));
2720: s.setString(3, swapNull(table));
2721: s.setBoolean(4, unique);
2722: s.setInt(5, approximateInInt);
2723: return s.executeQuery();
2724: }
2725:
2726: /////////////////////////////////////////////////////////////////////////
2727: //
2728: // JDBC 2.0 - New public methods
2729: //
2730: /////////////////////////////////////////////////////////////////////////
2731:
2732: /**
2733: * JDBC 2.0
2734: *
2735: * Does the database support the given result set type?
2736: *
2737: * @param type defined in java.sql.ResultSet
2738: * @return true if so
2739: * @see Connection
2740: */
2741: public boolean supportsResultSetType(int type) {
2742: if ((type == JDBC20Translation.TYPE_FORWARD_ONLY)
2743: || (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE)) {
2744: return true;
2745: }
2746: //we don't support TYPE_SCROLL_SENSITIVE yet.
2747: return false;
2748: }
2749:
2750: /**
2751: * JDBC 2.0
2752: *
2753: * Does the database support the concurrency type in combination
2754: * with the given result set type?
2755: *
2756: * @param type defined in java.sql.ResultSet
2757: * @param concurrency type defined in java.sql.ResultSet
2758: * @return true if so
2759: * @see Connection
2760: */
2761: public boolean supportsResultSetConcurrency(int type,
2762: int concurrency) {
2763: if (type == JDBC20Translation.TYPE_SCROLL_SENSITIVE) {
2764: // (TYPE_SCROLL_SENSITIVE, *)
2765: return false;
2766: } else {
2767: // (FORWARD_ONLY, CONCUR_UPDATABLE)
2768: // (FORWARD_ONLY, CONCUR_READ_ONLY)
2769: // (TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE)
2770: // (TYPE_SCROLL_INSENSITIVE, READ_ONLY)
2771: return true;
2772: }
2773: }
2774:
2775: /**
2776: * JDBC 2.0
2777: *
2778: * Determine whether a result set's updates are visible.
2779: *
2780: * @param type result set type, i.e. ResultSet.TYPE_XXX
2781: * @return true if updates are visible for the result set type
2782: */
2783: public boolean ownUpdatesAreVisible(int type) {
2784: if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) {
2785: return true;
2786: } else {
2787: return false;
2788: }
2789: }
2790:
2791: /**
2792: * JDBC 2.0
2793: *
2794: * Determine whether a result set's deletes are visible.
2795: *
2796: * @param type result set type, i.e. ResultSet.TYPE_XXX
2797: * @return true if deletes are visible for the result set type
2798: */
2799: public boolean ownDeletesAreVisible(int type) {
2800: if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) {
2801: return true;
2802: } else {
2803: return false;
2804: }
2805: }
2806:
2807: /**
2808: * JDBC 2.0
2809: *
2810: * Determine whether a result set's inserts are visible.
2811: *
2812: * @param type result set type, i.e. ResultSet.TYPE_XXX
2813: * @return true if inserts are visible for the result set type
2814: */
2815: public boolean ownInsertsAreVisible(int type) {
2816: return false;
2817: }
2818:
2819: // Since Derby materializes a forward only ResultSet incrementally, it is
2820: // possible to see changes made by others and hence following 3 metadata
2821: // calls will return true for forward only ResultSets.
2822:
2823: /**
2824: * JDBC 2.0
2825: *
2826: * Determine whether updates made by others are visible.
2827: *
2828: * @param type result set type, i.e. ResultSet.TYPE_XXX
2829: * @return true if updates are visible for the result set type
2830: */
2831: public boolean othersUpdatesAreVisible(int type) {
2832: if (type == JDBC20Translation.TYPE_FORWARD_ONLY)
2833: return true;
2834: return false;
2835: }
2836:
2837: /**
2838: * JDBC 2.0
2839: *
2840: * Determine whether deletes made by others are visible.
2841: *
2842: * @param type result set type, i.e. ResultSet.TYPE_XXX
2843: * @return true if deletes are visible for the result set type
2844: */
2845: public boolean othersDeletesAreVisible(int type) {
2846: if (type == JDBC20Translation.TYPE_FORWARD_ONLY)
2847: return true;
2848: return false;
2849: }
2850:
2851: /**
2852: * JDBC 2.0
2853: *
2854: * Determine whether inserts made by others are visible.
2855: *
2856: * @param type result set type, i.e. ResultSet.TYPE_XXX
2857: * @return true if inserts are visible for the result set type
2858: */
2859: public boolean othersInsertsAreVisible(int type) {
2860: if (type == JDBC20Translation.TYPE_FORWARD_ONLY)
2861: return true;
2862: return false;
2863: }
2864:
2865: /**
2866: * JDBC 2.0
2867: *
2868: * Determine whether or not a visible row update can be detected by
2869: * calling ResultSet.rowUpdated().
2870: *
2871: * @param type result set type, i.e. ResultSet.TYPE_XXX
2872: * @return true if updates are detected by the resultset type
2873: */
2874: public boolean updatesAreDetected(int type) {
2875: if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) {
2876: return true;
2877: } else {
2878: // For forward only resultsets, we move to before the next
2879: // row after a update and that is why updatesAreDetected
2880: // returns false.
2881: return false;
2882: }
2883: }
2884:
2885: /**
2886: * JDBC 2.0
2887: *
2888: * Determine whether or not a visible row delete can be detected by
2889: * calling ResultSet.rowDeleted(). If deletesAreDetected()
2890: * returns false, then deleted rows are removed from the result set.
2891: *
2892: * @param type result set type, i.e. ResultSet.TYPE_XXX
2893: * @return true if deletes are detected by the resultset type
2894: */
2895: public boolean deletesAreDetected(int type) {
2896: if (type == JDBC20Translation.TYPE_SCROLL_INSENSITIVE) {
2897: return true;
2898: } else {
2899: // For forward only resultsets, we move to before the next
2900: // row after a delete and that is why deletesAreDetected
2901: // returns false
2902: return false;
2903: }
2904: }
2905:
2906: /**
2907: * JDBC 2.0
2908: *
2909: * Determine whether or not a visible row insert can be detected
2910: * by calling ResultSet.rowInserted().
2911: *
2912: * @param type result set type, i.e. ResultSet.TYPE_XXX
2913: * @return true if inserts are detected by the resultset type
2914: */
2915: public boolean insertsAreDetected(int type) {
2916: return false;
2917: }
2918:
2919: /**
2920: * JDBC 2.0
2921: *
2922: * Return true if the driver supports batch updates, else return false.
2923: *
2924: */
2925: public boolean supportsBatchUpdates() {
2926: return true;
2927: }
2928:
2929: /**
2930: * JDBC 2.0
2931: *
2932: * Get a description of the user-defined types defined in a particular
2933: * schema. Schema specific UDTs may have type JAVA_OBJECT, STRUCT,
2934: * or DISTINCT.
2935: *
2936: * <P>Only types matching the catalog, schema, type name and type
2937: * criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
2938: * and TYPE_NAME. The type name parameter may be a fully qualified
2939: * name. In this case, the catalog and schemaPattern parameters are
2940: * ignored.
2941: *
2942: * <P>Each type description has the following columns:
2943: * <OL>
2944: * <LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
2945: * <LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
2946: * <LI><B>TYPE_NAME</B> String => type name
2947: * <LI><B>CLASS_NAME</B> String => Java class name
2948: * <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
2949: * One of JAVA_OBJECT, STRUCT, or DISTINCT
2950: * <LI><B>REMARKS</B> String => explanatory comment on the type
2951: * <LI><B>BASE_TYPE</B> short => type code of the source type of
2952: * a DISTINCT type or the type that implements the user-generated
2953: * reference type of the SELF_REFERENCING_COLUMN of a structured
2954: * type as defined in java.sql.Types (<code>null</code> if
2955: * DATA_TYPE is not DISTINCT or not STRUCT with
2956: * REFERENCE_GENERATION = USER_DEFINED)
2957: * </OL>
2958: *
2959: * <P><B>Note:</B> If the driver does not support UDTs then an empty
2960: * result set is returned.
2961: *
2962: * @param catalog a catalog name; "" retrieves those without a
2963: * catalog; null means drop catalog name from the selection criteria
2964: * @param schemaPattern a schema name pattern; "" retrieves those
2965: * without a schema
2966: * @param typeNamePattern a type name pattern; may be a fully qualified
2967: * name
2968: * @param types a list of user-named types to include (JAVA_OBJECT,
2969: * STRUCT, or DISTINCT); null returns all types
2970: * @return ResultSet - each row is a type description
2971: * @exception SQLException if a database-access error occurs.
2972: */
2973: public ResultSet getUDTs(String catalog, String schemaPattern,
2974: String typeNamePattern, int[] types) throws SQLException {
2975: //we don't have support for catalog names
2976: //we don't have java class types per schema, instead it's per database and hence
2977: //we ignore schemapattern.
2978: //the only type of user-named types we support are JAVA_OBJECT
2979: synchronized (getConnectionSynchronization()) {
2980: setupContextStack();
2981: ResultSet rs = null;
2982: int getClassTypes = 0;
2983: try {
2984: String queryText = getQueryDescriptions(false)
2985: .getProperty("getUDTs");
2986:
2987: if (types != null && types.length >= 1) {
2988: for (int i = 0; i < types.length; i++) {
2989: if (types[i] == java.sql.Types.JAVA_OBJECT)
2990: getClassTypes = 1;
2991: }
2992: } else
2993: getClassTypes = 1;
2994:
2995: PreparedStatement s = getEmbedConnection()
2996: .prepareMetaDataStatement(queryText);
2997:
2998: s.setInt(1, java.sql.Types.JAVA_OBJECT);
2999: s.setString(2, catalog);
3000: s.setString(3, schemaPattern);
3001: s.setString(4, swapNull(typeNamePattern));
3002: s.setInt(5, getClassTypes);
3003:
3004: rs = s.executeQuery();
3005: } finally {
3006: restoreContextStack();
3007: }
3008: return rs;
3009: }
3010: }
3011:
3012: /**
3013: * JDBC 2.0
3014: *
3015: * Return the connection that produced this metadata object.
3016: *
3017: */
3018: public Connection getConnection() {
3019: return getEmbedConnection().getApplicationConnection();
3020: }
3021:
3022: /**
3023: Following methods are for the new JDBC 3.0 methods in java.sql.DatabaseMetaData
3024: (see the JDBC 3.0 spec). We have the JDBC 3.0 methods in Local20
3025: package, so we don't have to have a new class in Local30.
3026: The new JDBC 3.0 methods don't make use of any new JDBC3.0 classes and
3027: so this will work fine in jdbc2.0 configuration.
3028: */
3029:
3030: /////////////////////////////////////////////////////////////////////////
3031: //
3032: // JDBC 3.0 - New public methods
3033: //
3034: /////////////////////////////////////////////////////////////////////////
3035: /**
3036: * JDBC 3.0
3037: *
3038: * Retrieves whether this database supports statement pooling.
3039: *
3040: * @return true if statement pooling is supported; false otherwise
3041: */
3042: public boolean supportsStatementPooling() {
3043: return false;
3044: }
3045:
3046: /**
3047: * JDBC 3.0
3048: *
3049: * Retrieves whether this database supports savepoints.
3050: *
3051: * @return true if savepoints are supported; false otherwise
3052: */
3053: public boolean supportsSavepoints() {
3054: return true;
3055: }
3056:
3057: /**
3058: * JDBC 3.0
3059: *
3060: * Retrieves whether this database supports named parameters to callable statements.
3061: *
3062: * @return true if named parameters are supported; false otherwise
3063: */
3064: public boolean supportsNamedParameters() {
3065: return false;
3066: }
3067:
3068: /**
3069: * JDBC 3.0
3070: *
3071: * Retrieves whether it is possible to have multiple ResultSet objects returned from a
3072: * CallableStatement object simultaneously.
3073: *
3074: * @return true if a CallableStatement object can return multiple ResultSet objects
3075: * simultaneously; false otherwise
3076: */
3077: public boolean supportsMultipleOpenResults() {
3078: return true;
3079: }
3080:
3081: /**
3082: * JDBC 3.0
3083: *
3084: * Retrieves whether auto-generated keys can be retrieved after a statement
3085: * has been executed.
3086: *
3087: * @return true if auto-generated keys can be retrieved after a statement has
3088: * executed; false otherwise
3089: */
3090: public boolean supportsGetGeneratedKeys() {
3091: /*
3092: * Currently reverting the returned value to false until there
3093: * is more support for autogenerated keys in Derby.
3094: * (such as support for specifying the returned columns for
3095: * the autogenerated key)
3096: */
3097: return false;
3098: }
3099:
3100: /**
3101: * JDBC 3.0
3102: *
3103: * Retrieves whether this database supports the given result set holdability.
3104: *
3105: * @param holdability - one of the following constants:
3106: * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
3107: * @return true if so; false otherwise
3108: * executed; false otherwise
3109: */
3110: public boolean supportsResultSetHoldability(int holdability) {
3111: return true;
3112: }
3113:
3114: /**
3115: * JDBC 3.0
3116: *
3117: * Retrieves the default holdability of this ResultSet object.
3118: *
3119: * @return the default holdability which is ResultSet.HOLD_CURSORS_OVER_COMMIT
3120: */
3121: public int getResultSetHoldability() {
3122: return JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
3123: }
3124:
3125: /**
3126: * JDBC 3.0
3127: *
3128: * Retrieves the major version number of the underlying database.
3129: *
3130: * @return the underlying database's major version
3131: */
3132: public int getDatabaseMajorVersion() {
3133: ProductVersionHolder pvh = Monitor.getMonitor()
3134: .getEngineVersion();
3135: if (pvh == null) {
3136: return -1;
3137: }
3138: return pvh.getMajorVersion();
3139: }
3140:
3141: /**
3142: * JDBC 3.0
3143: *
3144: * Retrieves the minor version number of the underlying database.
3145: *
3146: * @return the underlying database's minor version
3147: */
3148: public int getDatabaseMinorVersion() {
3149: ProductVersionHolder pvh = Monitor.getMonitor()
3150: .getEngineVersion();
3151: if (pvh == null) {
3152: return -1;
3153: }
3154: return pvh.getMinorVersion();
3155: }
3156:
3157: /**
3158: * JDBC 3.0
3159: *
3160: * Retrieves the major JDBC version number for this driver.
3161: *
3162: * @return JDBC version major number
3163: */
3164: public int getJDBCMajorVersion() {
3165: return 3;
3166: }
3167:
3168: /**
3169: * JDBC 3.0
3170: *
3171: * Retrieves the minor JDBC version number for this driver.
3172: *
3173: * @return JDBC version minor number
3174: */
3175: public int getJDBCMinorVersion() {
3176: return 0;
3177: }
3178:
3179: /**
3180: * JDBC 3.0
3181: *
3182: * Indicates whether the SQLSTATEs returned by SQLException.getSQLState
3183: * is X/Open (now known as Open Group) SQL CLI or SQL99.
3184: *
3185: * @return the type of SQLSTATEs, one of: sqlStateXOpen or sqlStateSQL99
3186: */
3187: public int getSQLStateType() {
3188: return JDBC30Translation.SQL_STATE_SQL99;
3189: }
3190:
3191: /**
3192: * JDBC 3.0
3193: *
3194: * Indicates whether updates made to a LOB are made on a copy or
3195: * directly to the LOB.
3196: *
3197: * @return true if updates are made to a copy of the LOB; false if
3198: * updates are made directly to the LOB
3199: * @exception SQLException Feature not implemented for now.
3200: */
3201: public boolean locatorsUpdateCopy() throws SQLException {
3202: return false;
3203: }
3204:
3205: /**
3206: * JDBC 3.0
3207: *
3208: * Retrieves a description of the user-defined type (UDT) hierarchies defined
3209: * in a particular schema in this database. Only the immediate super type/ sub type
3210: * relationship is modeled.
3211: *
3212: * @param catalog - a catalog name; "" retrieves those without a catalog;
3213: * null means drop catalog name from the selection criteria
3214: * @param schemaPattern - a schema name pattern; "" retrieves those without a schema
3215: * @param typeNamePattern - a UDT name pattern; may be a fully-qualified name
3216: * @return a ResultSet object in which a row gives information about the designated UDT
3217: * @exception SQLException Feature not implemented for now.
3218: */
3219: public ResultSet getSuperTypes(String catalog,
3220: String schemaPattern, String typeNamePattern)
3221: throws SQLException {
3222: return getSimpleQuery("getSuperTypes");
3223: }
3224:
3225: /**
3226: * JDBC 3.0
3227: *
3228: * Retrieves a description of the table hierarchies defined in a particular
3229: * schema in this database.
3230: *
3231: * @param catalog - a catalog name; "" retrieves those without a catalog;
3232: * null means drop catalog name from the selection criteria
3233: * @param schemaPattern - a schema name pattern; "" retrieves those without a schema
3234: * @param typeNamePattern - a UDT name pattern; may be a fully-qualified name
3235: * @return a ResultSet object in which each row is a type description
3236: * @exception SQLException if a database access error occurs
3237: */
3238: public ResultSet getSuperTables(String catalog,
3239: String schemaPattern, String typeNamePattern)
3240: throws SQLException {
3241: return getSimpleQuery("getSuperTables");
3242: }
3243:
3244: /**
3245: * JDBC 3.0
3246: *
3247: * Retrieves a description of the given attribute of the given type for a
3248: * user-defined type (UDT) that is available in the given schema and catalog.
3249: *
3250: * @param catalog - a catalog name; must match the catalog name as it is
3251: * stored in the database; "" retrieves those without a catalog; null means that
3252: * the catalog name should not be used to narrow the search
3253: * @param schemaPattern - a schema name pattern; "" retrieves those without a schema;
3254: * null means that the schema name should not be used to narrow the search
3255: * @param typeNamePattern - a type name pattern; must match the type name as it is
3256: * stored in the database
3257: * @param attributeNamePattern - an attribute name pattern; must match the attribute
3258: * name as it is declared in the database
3259: * @return a ResultSet object in which each row is a type description
3260: * @exception SQLException if a database access error occurs.
3261: */
3262: public ResultSet getAttributes(String catalog,
3263: String schemaPattern, String typeNamePattern,
3264: String attributeNamePattern) throws SQLException {
3265: return getSimpleQuery("getAttributes");
3266: }
3267:
3268: /////////////////////////////////////////////////////////////////////////
3269: //
3270: // JDBC 4.0 - New public methods
3271: //
3272: /////////////////////////////////////////////////////////////////////////
3273:
3274: /**
3275: * JDBC 4.0
3276: *
3277: * <p>Returns a list of the client info properties supported by
3278: * the driver. The result set contains the following columns:
3279: *
3280: * <p>
3281: * <ol>
3282: * <li>NAME String=> The name of the client info property.</li>
3283: * <li>MAX_LEN int=> The maximum length of the value for the
3284: * property.</li>
3285: * <li>DEFAULT_VALUE String=> The default value of the property.</li>
3286: * <li>DESCRIPTION String=> A description of the property.</li>
3287: * </ol>
3288: *
3289: * <p>The <code>ResultSet</code> is sorted by the NAME column.
3290: *
3291: * @return A <code>ResultSet</code> object; each row is a
3292: * supported client info property
3293: * @exception SQLException if an error occurs
3294: */
3295: public ResultSet getClientInfoProperties() throws SQLException {
3296: return getSimpleQuery("getClientInfoProperties");
3297: }
3298:
3299: /**
3300: * JDBC 4.0
3301: *
3302: * <p>Get the schema names available in this database. The results
3303: * are ordered by schema name.
3304: *
3305: * <p>The schema columns are:
3306: * <ol>
3307: * <li><strong>TABLE_SCHEM</strong> String => schema name</li>
3308: * <li><strong>TABLE_CATALOG</strong> String => catalog name
3309: * (may be <code>null</code>)</li>
3310: * </ol>
3311: *
3312: * @param catalog catalog name used to narrow down the search; ""
3313: * means no catalog, <code>null</code> means any catalog
3314: * @param schemaPattern schema name used to narrow down the
3315: * search, <code>null</code> means schema name should not be used
3316: * to narrow down search
3317: * @return a <code>ResultSet</code> object in which each row is a
3318: * schema description
3319: * @exception SQLException if a database error occurs
3320: */
3321: public ResultSet getSchemas(String catalog, String schemaPattern)
3322: throws SQLException {
3323: PreparedStatement s = getPreparedQuery("getSchemas");
3324: s.setString(1, swapNull(catalog));
3325: s.setString(2, swapNull(schemaPattern));
3326: return s.executeQuery();
3327: }
3328:
3329: //////////////////////////////////////////////////////////////
3330: //
3331: // MISC
3332: //
3333: //////////////////////////////////////////////////////////////
3334:
3335: /**
3336: * Get metadata that the client driver will cache. The metadata is
3337: * fetched using SYSIBM.METADATA (found in metadata_net.properties).
3338: *
3339: * @return the result set returned by SYSIBM.METADATA
3340: * @exception SQLException if a database error occurs
3341: */
3342: public ResultSet getClientCachedMetaData() throws SQLException {
3343: return getSimpleQuery("METADATA", true);
3344: }
3345:
3346: /*
3347: * utility helper routines:
3348: */
3349:
3350: /**
3351: * Execute a query in metadata.properties (or SPS in the SYS
3352: * schema) or metadata_net.properties (or SPS in the SYSIBM
3353: * schema).
3354: *
3355: * @param nameKey the name of the query
3356: * @param net if <code>true</code>, execute a query in
3357: * metadata_net.properties; otherwise, execute a query in
3358: * metadata.properties
3359: * @return a <code>ResultSet</code> value
3360: * @exception SQLException if a database error occurs
3361: */
3362: private ResultSet getSimpleQuery(String nameKey, boolean net)
3363: throws SQLException {
3364: PreparedStatement ps = getPreparedQuery(nameKey, net);
3365: if (ps == null)
3366: return null;
3367:
3368: return ps.executeQuery();
3369: }
3370:
3371: /**
3372: * Execute a query in metadata.properties, or an SPS in the SYS
3373: * schema.
3374: *
3375: * @param nameKey the name of the query
3376: * @return a <code>ResultSet</code> value
3377: * @exception SQLException if a database error occurs
3378: */
3379: protected ResultSet getSimpleQuery(String nameKey)
3380: throws SQLException {
3381: return getSimpleQuery(nameKey, false);
3382: }
3383:
3384: /**
3385: * Get a stored prepared statement from the system tables.
3386: *
3387: * @param nameKey the name of the query
3388: * @param net if <code>true</code>, find query in SYSIBM schema;
3389: * otherwise, find query in SYS schema
3390: * @return a <code>PreparedStatement</code> value
3391: * @exception SQLException if a database error occurs
3392: */
3393: private PreparedStatement getPreparedQueryUsingSystemTables(
3394: String nameKey, boolean net) throws SQLException {
3395: synchronized (getConnectionSynchronization()) {
3396: setupContextStack();
3397: PreparedStatement ps = null;
3398:
3399: try {
3400: String queryText = getQueryDescriptions(net)
3401: .getProperty(nameKey);
3402: if (queryText == null) {
3403: throw Util.notImplemented(nameKey);
3404: }
3405:
3406: ps = prepareSPS(nameKey, queryText, net);
3407: }
3408:
3409: catch (Throwable t) {
3410: throw handleException(t);
3411: }
3412:
3413: finally {
3414: restoreContextStack();
3415: }
3416: return ps;
3417: }
3418: }
3419:
3420: /**
3421: * Either get the prepared query for the metadata call from the
3422: * system tables, or from the metadata.properties or
3423: * metadata_net.properties file.
3424: * In soft upgrade mode, the queries stored in the system tables
3425: * might not be upto date with the Derby engine release because
3426: * system tables can't be modified in backward incompatible way in
3427: * soft upgrade mode. Because of this, if the database is in
3428: * soft upgrade mode, get the queries from metadata.properties
3429: * file rather than from the system tables.
3430: *
3431: * Getting queries from metadata(_net).properties might cause problems
3432: * if system catalogs have been changed between versions either by
3433: * addition of columns or have new catalogs. To continue
3434: * to support soft upgrade from older versions of database, find
3435: * query that most closely matches database dictionary version.
3436: *
3437: * @param queryName Name of the metadata query for which we need
3438: * a prepared statement
3439: * @param net if <code>true</code>, use metadata_net.properties
3440: * instead of metadata.properties
3441: * @return PreparedStatement
3442: * @exception SQLException if a database error occurs
3443: */
3444: private PreparedStatement getPreparedQuery(String queryName,
3445: boolean net) throws SQLException {
3446: PreparedStatement s;
3447: //We can safely goto system table since we are not in soft upgrade
3448: //mode and hence metadata sql in system tables are uptodate
3449: //with this Derby release.
3450: if (notInSoftUpgradeMode())
3451: s = getPreparedQueryUsingSystemTables(queryName, net);
3452: else {
3453: try {
3454: //Can't use stored prepared statements because we are in soft upgrade
3455: //mode and hence need to get metadata sql from metadata.properties file
3456: //or metadata_net.properties
3457: String queryText = getQueryFromDescription(queryName,
3458: net);
3459: s = getEmbedConnection().prepareMetaDataStatement(
3460: queryText);
3461: } catch (Throwable t) {
3462: throw handleException(t);
3463: }
3464: }
3465: return s;
3466: }
3467:
3468: /**
3469: * Get a prepared query from system tables or metadata.properties.
3470: *
3471: * @param queryName name of the query
3472: * @return a <code>PreparedStatement</code> value
3473: * @exception SQLException if a database error occurs
3474: */
3475: protected PreparedStatement getPreparedQuery(String queryName)
3476: throws SQLException {
3477: return getPreparedQuery(queryName, false);
3478: }
3479:
3480: /**
3481: * Given a queryName, find closest match in queryDescriptions. This method
3482: * should be called in soft-upgrade mode only, where current software version
3483: * doesn't match dictionary version. For these cases, there may be
3484: * multiple entries in queryDescriptions for given queryName. Find a
3485: * version of the query that closely matches dictionary version.
3486: *
3487: * This method is currently coded to handle two specific queries,
3488: * getColumnPrivileges and getTablePrivileges. Derby databases that are 10.1
3489: * or earlier will not have new system tables added for 10.2 for privileges.
3490: *
3491: * It should be possible to automate finding closest match by generating
3492: * all Major_Minor versions between software version and dictionary version
3493: * and try each one from Dictionary version to current version. Since only
3494: * needed for two queries, overhead may not be worth it yet.
3495: *
3496: * @param queryName name of the query
3497: * @param net if <code>true</code>, get the query from
3498: * metadata_net.properties instead of metadata.properties
3499: * @return the query text
3500: * @exception StandardException if an error occurs
3501: */
3502: private String getQueryFromDescription(String queryName, boolean net)
3503: throws StandardException {
3504: DataDictionary dd = getLanguageConnectionContext()
3505: .getDataDictionary();
3506:
3507: // If dictionary version is below 10.2, special case
3508: // getColumnPrivileges and getTablePrivileges since new system tables
3509: // for privileges wouldn't be present.
3510: if (!dd
3511: .checkVersion(DataDictionary.DD_VERSION_DERBY_10_2,
3512: null)) {
3513: if (queryName.equals("getColumnPrivileges"))
3514: queryName = "getColumnPrivileges_10_1";
3515:
3516: if (queryName.equals("getTablePrivileges"))
3517: queryName = "getTablePrivileges_10_1";
3518: }
3519:
3520: return getQueryDescriptions(net).getProperty(queryName);
3521: }
3522:
3523: /*
3524: ** Given a SPS name and a query text it returns a
3525: ** java.sql.PreparedStatement for the SPS. If the SPS
3526: ** doeesn't exist is created.
3527: **
3528: */
3529: private PreparedStatement prepareSPS(String spsName,
3530: String spsText, boolean net) throws StandardException,
3531: SQLException {
3532:
3533: LanguageConnectionContext lcc = getLanguageConnectionContext();
3534:
3535: /* We now need to do this in sub transaction because we could possibly recompile SPS
3536: * later, and the recompile is in a sub transaction, and will update the SYSSTATEMENTS
3537: * entry. Don't want to block.
3538: */
3539: lcc.beginNestedTransaction(true);
3540:
3541: DataDictionary dd = getLanguageConnectionContext()
3542: .getDataDictionary();
3543: SPSDescriptor spsd = dd.getSPSDescriptor(spsName, net ? dd
3544: .getSysIBMSchemaDescriptor() : dd
3545: .getSystemSchemaDescriptor());
3546: lcc.commitNestedTransaction();
3547:
3548: if (spsd == null) {
3549: throw Util.notImplemented(spsName);
3550: }
3551:
3552: /* manish:
3553: There should be a nicer way of getting a
3554: java.sql.PreparedStatement from an SPS descriptor!
3555: */
3556: /*
3557: ** It is unnecessarily expensive to get the
3558: ** the statement, and then send an EXECUTE
3559: ** statement, but we have no (easy) way of turning
3560: ** the statement into a java.sql.PreparedStatement.
3561: */
3562: String queryText = "EXECUTE STATEMENT "
3563: + (net ? "SYSIBM" : "SYS") + ".\"" + spsName + "\"";
3564: return getEmbedConnection().prepareMetaDataStatement(queryText);
3565:
3566: }
3567:
3568: static final protected String swapNull(String s) {
3569: return (s == null ? "%" : s);
3570: }
3571:
3572: /**
3573: * Gets the constant action factory
3574: *
3575: * @return the constant action factory.
3576: *
3577: * @exception StandardException Thrown on failur4e
3578: */
3579: private GenericConstantActionFactory getGenericConstantActionFactory()
3580: throws StandardException {
3581: if (constantActionFactory == null) {
3582: GenericExecutionFactory execFactory = (GenericExecutionFactory) getLanguageConnectionContext()
3583: .getLanguageConnectionFactory()
3584: .getExecutionFactory();
3585: constantActionFactory = execFactory
3586: .getConstantActionFactory();
3587: }
3588:
3589: return constantActionFactory;
3590: }
3591:
3592: /**
3593: * Gets the LanguageConnectionContext for this connection.
3594: *
3595: * @return the lcc for this connection
3596: *
3597: */
3598: private LanguageConnectionContext getLanguageConnectionContext() {
3599: return getEmbedConnection().getLanguageConnection();
3600: }
3601:
3602: /*
3603: ** Priv block code, moved out of the old Java2 version.
3604: */
3605:
3606: /**
3607: * Loads the query descriptions from metadata.properties and
3608: * metadata_net.properties into <code>queryDescriptions</code> and
3609: * <code>queryDescriptions_net</code>.
3610: */
3611: private void loadQueryDescriptions() {
3612: java.security.AccessController.doPrivileged(this );
3613: }
3614:
3615: /**
3616: * Performs a privileged action. Reads the query descriptions.
3617: *
3618: * @return <code>null</code>
3619: */
3620: public final Object run() {
3621: // SECURITY PERMISSION - IP3
3622: PBloadQueryDescriptions();
3623: return null;
3624: }
3625:
3626: }
|