Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
jTDS JDBC Driver Source Code Files
jTDS JDBC Driver Source Code Files are provided in the source package file, jtds-1.3.1-fyi.zip.
You can browse jTDS JDBC Driver Source Code files below:
✍: FYIcenter.com
⏎ net/sourceforge/jtds/jdbc/JtdsDatabaseMetaData.java
// jTDS JDBC Driver for Microsoft SQL Server and Sybase // Copyright (C) 2004 The jTDS Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // package net.sourceforge.jtds.jdbc; import java.sql.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * jTDS implementation of the java.sql.DatabaseMetaData interface. * <p> * Implementation note: * <p> * This is basically the code from the original jTDS driver. * Main changes relate to the need to support the new ResultSet * implementation. * <p> * TODO: Many of the system limits need to be revised to more accurately * reflect the target database constraints. In many cases limits are soft * and determined by bytes per column for example. Probably more of these * functions should be altered to return 0 but for now the original jTDS * values are returned. * * @author Craig Spannring * @author The FreeTDS project * @author Alin Sinpalean * created 17 March 2001 * @version $Id: JtdsDatabaseMetaData.java,v 1.37.2.4 2009-12-30 08:45:34 ickzon Exp $ */ public class JtdsDatabaseMetaData implements java.sql.DatabaseMetaData { static final int sqlStateXOpen = 1; // Internal data needed by this implemention. private final int tdsVersion; private final int serverType; private final JtdsConnection connection; /** * Length of a sysname object (table name, catalog name etc.) -- 128 for * TDS 7.0, 30 for earlier versions. */ int sysnameLength = 30; /** * <code>Boolean.TRUE</code> if identifiers are case sensitive (the server * was installed that way). Initially <code>null</code>, set the first time * any of the methods that check this are called. */ Boolean caseSensitive; public JtdsDatabaseMetaData(JtdsConnection connection) { this.connection = connection; tdsVersion = connection.getTdsVersion(); serverType = connection.getServerType(); if (tdsVersion >= Driver.TDS70) { sysnameLength = 128; } } //---------------------------------------------------------------------- // First, a variety of minor information about the target database. /** * Can all the procedures returned by getProcedures be called by the * current user? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean allProceduresAreCallable() throws SQLException { // Sybase - if accessible_sproc = Y in server info (normal case) return true return true; // per "Programming ODBC for SQLServer" Appendix A } /** * Can all the tables returned by getTable be SELECTed by the * current user? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean allTablesAreSelectable() throws SQLException { // Sybase sp_tables may return tables that you are not able to access. return connection.getServerType() == Driver.SQLSERVER; } /** * Does a data definition statement within a transaction force the * transaction to commit? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean dataDefinitionCausesTransactionCommit() throws SQLException { return false; } /** * Is a data definition statement within a transaction ignored? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean dataDefinitionIgnoredInTransactions() throws SQLException { return false; } /** * Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY blobs? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { return false; } /** * Get a description of a table's optimal set of columns that * uniquely identifies a row. They are ordered by SCOPE. * * <P>Each column description has the following columns: * <OL> * <LI> <B>SCOPE</B> short =>actual scope of result * <UL> * <LI> bestRowTemporary - very temporary, while using row * <LI> bestRowTransaction - valid for remainder of current transaction * * <LI> bestRowSession - valid for remainder of current session * </UL> * * <LI> <B>COLUMN_NAME</B> String =>column name * <LI> <B>DATA_TYPE</B> short =>SQL data type from java.sql.Types * <LI> <B>TYPE_NAME</B> String =>Data source dependent type name * <LI> <B>COLUMN_SIZE</B> int =>precision * <LI> <B>BUFFER_LENGTH</B> int =>not used * <LI> <B>DECIMAL_DIGITS</B> short =>scale * <LI> <B>PSEUDO_COLUMN</B> short =>is this a pseudo column like an * Oracle ROWID * <UL> * <LI> bestRowUnknown - may or may not be pseudo column * <LI> bestRowNotPseudo - is NOT a pseudo column * <LI> bestRowPseudo - is a pseudo column * </UL> * * </OL> * * * @param catalog a catalog name; "" retrieves those without a catalog; * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @param scope the scope of interest; use same values as SCOPE * @param nullable include columns that are nullable? * @return ResultSet - each row is a column description * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { String colNames[] = {"SCOPE", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "PSEUDO_COLUMN"}; int colTypes[] = {Types.SMALLINT, Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.SMALLINT, Types.SMALLINT}; String query = "sp_special_columns ?, ?, ?, ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, table); s.setString(2, schema); s.setString(3, catalog); s.setString(4, "R"); s.setString(5, "T"); s.setString(6, "U"); s.setInt(7, 3); // ODBC version 3 JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); while (rs.next()) { for (int i = 1; i <= colCnt; i++) { if (i == 3) { int type = TypeInfo.normalizeDataType(rs.getInt(i), connection.getUseLOBs()); rsTmp.updateInt(i, type); } else { rsTmp.updateObject(i, rs.getObject(i)); } } rsTmp.insertRow(); } rs.close(); // Do not close the statement, rsTmp is also built from it rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } /** * Get the catalog names available in this database. The results are * ordered by catalog name. <P> * * The catalog column is: * <OL> * <LI> <B>TABLE_CAT</B> String =>catalog name * </OL> * * * @return ResultSet - each row has a single String column * that is a catalog name * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getCatalogs() throws SQLException { String query = "exec sp_tables '', '', '%', NULL"; Statement s = connection.createStatement(); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(query); rs.setColumnCount(1); rs.setColLabel(1, "TABLE_CAT"); upperCaseColumnNames(rs); return rs; } /** * What's the separator between catalog and table name? * * @return the separator string * @throws SQLException if a database-access error occurs. */ public String getCatalogSeparator() throws SQLException { return "."; } /** * What's the database vendor's preferred term for "catalog"? * * @return the vendor term * @throws SQLException if a database-access error occurs. */ public String getCatalogTerm() throws SQLException { return "database"; } /** * Get a description of the access rights for a table's columns. <P> * * Only privileges matching the column name criteria are returned. They are * ordered by COLUMN_NAME and PRIVILEGE. <P> * * Each privilige description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>COLUMN_NAME</B> String =>column name * <LI> <B>GRANTOR</B> =>grantor of access (may be null) * <LI> <B>GRANTEE</B> String =>grantee of access * <LI> <B>PRIVILEGE</B> String =>name of access (SELECT, INSERT, UPDATE, * REFRENCES, ...) * <LI> <B>IS_GRANTABLE</B> String =>"YES" if grantee is permitted to * grant to others; "NO" if not; null if unknown * </OL> * * @param catalog a catalog name; "" retrieves those without a catalog; * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * schema * @param table a table name * @param columnNamePattern a column name pattern * @return ResultSet - each row is a column privilege description * @throws SQLException if a database-access error occurs. * * @see #getSearchStringEscape */ public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { String query = "sp_column_privileges ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, table); s.setString(2, schema); s.setString(3, catalog); s.setString(4, processEscapes(columnNamePattern)); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); rs.setColLabel(1, "TABLE_CAT"); rs.setColLabel(2, "TABLE_SCHEM"); upperCaseColumnNames(rs); return rs; } /** * Get a description of table columns available in a catalog. <P> * * Only column descriptions matching the catalog, schema, table and column * name criteria are returned. They are ordered by TABLE_SCHEM, TABLE_NAME * and ORDINAL_POSITION. <P> * * Each column description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>COLUMN_NAME</B> String =>column name * <LI> <B>DATA_TYPE</B> short =>SQL type from java.sql.Types * <LI> <B>TYPE_NAME</B> String =>Data source dependent type name * <LI> <B>COLUMN_SIZE</B> int =>column size. For char or date types this * is the maximum number of characters, for numeric or decimal types this * is precision. * <LI> <B>BUFFER_LENGTH</B> is not used. * <LI> <B>DECIMAL_DIGITS</B> int =>the number of fractional digits * <LI> <B>NUM_PREC_RADIX</B> int =>Radix (typically either 10 or 2) * <LI> <B>NULLABLE</B> int =>is NULL allowed? * <UL> * <LI> columnNoNulls - might not allow NULL values * <LI> columnNullable - definitely allows NULL values * <LI> columnNullableUnknown - nullability unknown * </UL> * * <LI> <B>REMARKS</B> String =>comment describing column (may be null) * * <LI> <B>COLUMN_DEF</B> String =>default value (may be null) * <LI> <B>SQL_DATA_TYPE</B> int =>unused * <LI> <B>SQL_DATETIME_SUB</B> int =>unused * <LI> <B>CHAR_OCTET_LENGTH</B> int =>for char types the maximum number * of bytes in the column * <LI> <B>ORDINAL_POSITION</B> int =>index of column in table (starting * at 1) * <LI> <B>IS_NULLABLE</B> String =>"NO" means column definitely does not * allow NULL values; "YES" means the column might allow NULL values. An * empty string means nobody knows. * <LI> <B>IS_AUTOINCREMENT</B> String =>"NO" means column is no identity * column; "YES" means it is. * </OL> * * * @param catalog a catalog name; "" retrieves those without a catalog; * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those without a schema * @param tableNamePattern a table name pattern * @param columnNamePattern a column name pattern * @return ResultSet - each row is a column description * @throws SQLException if a database-access error occurs. * * @see #getSearchStringEscape */ public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { String colNames[] = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATALOG", "SCOPE_SCHEMA", "SCOPE_TABLE", "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT" }; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT, Types.VARCHAR }; String query = "sp_columns ?, ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, processEscapes(tableNamePattern)); s.setString(2, processEscapes(schemaPattern)); s.setString(3, catalog); s.setString(4, processEscapes(columnNamePattern)); s.setInt(5, 3); // ODBC version 3 JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); // // Neither type of server returns exactly the data required by the JDBC3 standard. // The result data is copied to a cached result set and modified on the fly. // while (rs.next()) { String typeName = rs.getString(6); if (serverType == Driver.SYBASE) { // Sybase servers (older versions only return 14 columns) for (int i = 1; i <= 4; i++) { rsTmp.updateObject(i, rs.getObject(i)); } rsTmp.updateInt(5, TypeInfo.normalizeDataType(rs.getInt(5), connection.getUseLOBs())); rsTmp.updateString(6, typeName); for (int i = 8; i <= 12; i++) { rsTmp.updateObject(i, rs.getObject(i)); } if (colCnt >= 20) { // SYBASE 11.92, 12.5 for (int i = 13; i <= 18; i++) { rsTmp.updateObject(i, rs.getObject(i + 2)); } } else { // SYBASE 11.03 rsTmp.updateObject(16, rs.getObject(8)); rsTmp.updateObject(17, rs.getObject(14)); } if ("image".equals(typeName) || "text".equals(typeName)) { rsTmp.updateInt(7, Integer.MAX_VALUE); rsTmp.updateInt(16, Integer.MAX_VALUE); } else if ("univarchar".equals(typeName) || "unichar".equals(typeName)) { rsTmp.updateInt(7, rs.getInt(7) / 2); rsTmp.updateObject(16, rs.getObject(7)); } else { rsTmp.updateInt(7, rs.getInt(7)); } // add "IS_AUTOINCREMENT" value rsTmp.updateString( 23, typeName.toLowerCase().contains( "identity" ) ? "YES" : "NO" ); } else { // MS SQL Server - Mainly OK but we need to fix some data types. for (int i = 1; i <= colCnt; i++) { if (i == 5) { int type = TypeInfo.normalizeDataType(rs.getInt(i), connection.getUseLOBs()); rsTmp.updateInt(i, type); } else if (i == 19) { // This is the SS_DATA_TYPE column and contains the TDS // data type constant. We can use this to distinguish // varchar(max) from text on SQL2005. rsTmp.updateString(6, TdsData.getMSTypeName(rs.getString(6), rs.getInt(19))); } else { rsTmp.updateObject(i, rs.getObject(i)); } } // add "IS_AUTOINCREMENT" value rsTmp.updateString( 23, typeName.toLowerCase().contains( "identity" ) ? "YES" : "NO" ); } rsTmp.insertRow(); } rs.close(); rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } /** * Get a description of the foreign key columns in the foreign key table * that reference the primary key columns of the primary key table * (describe how one table imports another's key). This should normally * return a single foreign key/primary key pair (most tables only import a * foreign key from a table once.) They are ordered by FKTABLE_CAT, * FKTABLE_SCHEM, FKTABLE_NAME, and KEY_SEQ. <P> * * Each foreign key column description has the following columns: * <OL> * <LI> <B>PKTABLE_CAT</B> String =>primary key table catalog (may be * null) * <LI> <B>PKTABLE_SCHEM</B> String =>primary key table schema (may be * null) * <LI> <B>PKTABLE_NAME</B> String =>primary key table name * <LI> <B>PKCOLUMN_NAME</B> String =>primary key column name * <LI> <B>FKTABLE_CAT</B> String =>foreign key table catalog (may be * null) being exported (may be null) * <LI> <B>FKTABLE_SCHEM</B> String =>foreign key table schema (may be * null) being exported (may be null) * <LI> <B>FKTABLE_NAME</B> String =>foreign key table name being * exported * <LI> <B>FKCOLUMN_NAME</B> String =>foreign key column name being * exported * <LI> <B>KEY_SEQ</B> short =>sequence number within foreign key * <LI> <B>UPDATE_RULE</B> short =>What happens to foreign key when * primary is updated: * <UL> * <LI> importedNoAction - do not allow update of primary key if it has * been imported * <LI> importedKeyCascade - change imported key to agree with primary * key update * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been updated * <LI> importedKeySetDefault - change imported key to default values * if its primary key has been updated * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * </UL> * * <LI> <B>DELETE_RULE</B> short =>What happens to the foreign key when * primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it * has been imported * <LI> importedKeyCascade - delete rows that import a deleted key * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been deleted * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * <LI> importedKeySetDefault - change imported key to default if its * primary key has been deleted * </UL> * * <LI> <B>FK_NAME</B> String =>foreign key name (may be null) * <LI> <B>PK_NAME</B> String =>primary key name (may be null) * <LI> <B>DEFERRABILITY</B> short =>can the evaluation of foreign key * constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition * <LI> importedKeyNotDeferrable - see SQL92 for definition * </UL> * * </OL> * * @param primaryCatalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param primarySchema a schema name pattern; "" retrieves those without a schema * @param primaryTable the table name that exports the key * @param foreignCatalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param foreignSchema a schema name pattern; "" retrieves those without a schema * @param foreignTable the table name that imports the key * @return ResultSet - each row is a foreign key column description * @throws SQLException if a database-access error occurs. * * @see #getImportedKeys */ public java.sql.ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { String colNames[] = {"PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME", "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM", "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ", "UPDATE_RULE", "DELETE_RULE", "FK_NAME", "PK_NAME", "DEFERRABILITY"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT, Types.SMALLINT, Types.SMALLINT, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT}; String query = "sp_fkeys ?, ?, ?, ?, ?, ?"; if (primaryCatalog != null) { query = syscall(primaryCatalog, query); } else if (foreignCatalog != null) { query = syscall(foreignCatalog, query); } else { query = syscall(null, query); } CallableStatement s = connection.prepareCall(query); s.setString(1, primaryTable); s.setString(2, processEscapes(primarySchema)); s.setString(3, primaryCatalog); s.setString(4, foreignTable); s.setString(5, processEscapes(foreignSchema)); s.setString(6, foreignCatalog); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); int colCnt = rs.getMetaData().getColumnCount(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); while (rs.next()) { for (int i = 1; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } if (colCnt < 14) { rsTmp.updateShort(14, (short)DatabaseMetaData.importedKeyNotDeferrable); } rsTmp.insertRow(); } rs.close(); rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } /** * Returns the name of this database product. * * @return database product name * @throws SQLException if a database-access error occurs. */ public String getDatabaseProductName() throws SQLException { return connection.getDatabaseProductName(); } /** * Returns the version of this database product. * * @return database version * @throws SQLException if a database-access error occurs. */ public String getDatabaseProductVersion() throws SQLException { return connection.getDatabaseProductVersion(); } //---------------------------------------------------------------------- /** * Returns the database's default transaction isolation level. The values * are defined in java.sql.Connection. * * @return the default isolation level * @throws SQLException if a database-access error occurs. * * @see Connection */ public int getDefaultTransactionIsolation() throws SQLException { return Connection.TRANSACTION_READ_COMMITTED; } /** * Returns this JDBC driver's major version number. * * @return JDBC driver major version */ public int getDriverMajorVersion() { return Driver.MAJOR_VERSION; } /** * Returns this JDBC driver's minor version number. * * @return JDBC driver minor version number */ public int getDriverMinorVersion() { return Driver.MINOR_VERSION; } /** * Returns the name of this JDBC driver. * * @return JDBC driver name * @throws SQLException if a database-access error occurs. */ public String getDriverName() throws SQLException { return "jTDS Type 4 JDBC Driver for MS SQL Server and Sybase"; } /** * Returns the version of this JDBC driver. * * @return JDBC driver version * @throws SQLException if a database-access error occurs. */ public String getDriverVersion() throws SQLException { return Driver.getVersion(); } /** * Get a description of the foreign key columns that reference a table's * primary key columns (the foreign keys exported by a table). They are * ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and KEY_SEQ. * <p> * Each foreign key column description has the following columns: * <OL> * <LI> <B>PKTABLE_CAT</B> String =>primary key table catalog (may be * null) * <LI> <B>PKTABLE_SCHEM</B> String =>primary key table schema (may be * null) * <LI> <B>PKTABLE_NAME</B> String =>primary key table name * <LI> <B>PKCOLUMN_NAME</B> String =>primary key column name * <LI> <B>FKTABLE_CAT</B> String =>foreign key table catalog (may be * null) being exported (may be null) * <LI> <B>FKTABLE_SCHEM</B> String =>foreign key table schema (may be * null) being exported (may be null) * <LI> <B>FKTABLE_NAME</B> String =>foreign key table name being * exported * <LI> <B>FKCOLUMN_NAME</B> String =>foreign key column name being * exported * <LI> <B>KEY_SEQ</B> short =>sequence number within foreign key * <LI> <B>UPDATE_RULE</B> short =>What happens to foreign key when * primary is updated: * <UL> * <LI> importedNoAction - do not allow update of primary key if it has * been imported * <LI> importedKeyCascade - change imported key to agree with primary * key update * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been updated * <LI> importedKeySetDefault - change imported key to default values * if its primary key has been updated * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * </UL> * * <LI> <B>DELETE_RULE</B> short =>What happens to the foreign key when * primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it * has been imported * <LI> importedKeyCascade - delete rows that import a deleted key * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been deleted * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * <LI> importedKeySetDefault - change imported key to default if its * primary key has been deleted * </UL> * * <LI> <B>FK_NAME</B> String =>foreign key name (may be null) * <LI> <B>PK_NAME</B> String =>primary key name (may be null) * <LI> <B>DEFERRABILITY</B> short =>can the evaluation of foreign key * constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition * <LI> importedKeyNotDeferrable - see SQL92 for definition * </UL> * * </OL> * * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @return ResultSet - each row is a foreign key column description * @throws SQLException if a database-access error occurs. * * @see #getImportedKeys */ public java.sql.ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { return getCrossReference(catalog, schema, table, null, null, null); } /** * Get all the "extra" characters that can be used in unquoted identifier * names (those beyond a-z, A-Z, 0-9 and _). * * @return the string containing the extra characters * @throws SQLException if a database-access error occurs. */ public String getExtraNameCharacters() throws SQLException { // MS driver returns "$#@" Sybase JConnect returns "@#$��" return "$#@"; } /** * Returns the string used to quote SQL identifiers. This returns a space " * " if identifier quoting isn't supported. A JDBC-Compliant driver always * uses a double quote character. * * @return the quoting string * @throws SQLException if a database-access error occurs. */ public String getIdentifierQuoteString() throws SQLException { return "\""; } /** * Get a description of the primary key columns that are referenced by a * table's foreign key columns (the primary keys imported by a table). They * are ordered by PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ. * <p> * Each primary key column description has the following columns: * <OL> * <LI> <B>PKTABLE_CAT</B> String =>primary key table catalog being * imported (may be null) * <LI> <B>PKTABLE_SCHEM</B> String =>primary key table schema being * imported (may be null) * <LI> <B>PKTABLE_NAME</B> String =>primary key table name being * imported * <LI> <B>PKCOLUMN_NAME</B> String =>primary key column name being * imported * <LI> <B>FKTABLE_CAT</B> String =>foreign key table catalog (may be * null) * <LI> <B>FKTABLE_SCHEM</B> String =>foreign key table schema (may be * null) * <LI> <B>FKTABLE_NAME</B> String =>foreign key table name * <LI> <B>FKCOLUMN_NAME</B> String =>foreign key column name * <LI> <B>KEY_SEQ</B> short =>sequence number within foreign key * <LI> <B>UPDATE_RULE</B> short =>What happens to foreign key when * primary is updated: * <UL> * <LI> importedNoAction - do not allow update of primary key if it has * been imported * <LI> importedKeyCascade - change imported key to agree with primary * key update * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been updated * <LI> importedKeySetDefault - change imported key to default values * if its primary key has been updated * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * </UL> * * <LI> <B>DELETE_RULE</B> short =>What happens to the foreign key when * primary is deleted. * <UL> * <LI> importedKeyNoAction - do not allow delete of primary key if it * has been imported * <LI> importedKeyCascade - delete rows that import a deleted key * <LI> importedKeySetNull - change imported key to NULL if its primary * key has been deleted * <LI> importedKeyRestrict - same as importedKeyNoAction (for ODBC 2.x * compatibility) * <LI> importedKeySetDefault - change imported key to default if its * primary key has been deleted * </UL> * * <LI> <B>FK_NAME</B> String =>foreign key name (may be null) * <LI> <B>PK_NAME</B> String =>primary key name (may be null) * <LI> <B>DEFERRABILITY</B> short =>can the evaluation of foreign key * constraints be deferred until commit * <UL> * <LI> importedKeyInitiallyDeferred - see SQL92 for definition * <LI> importedKeyInitiallyImmediate - see SQL92 for definition * <LI> importedKeyNotDeferrable - see SQL92 for definition * </UL> * * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @return ResultSet - each row is a primary key column description * @throws SQLException if a database-access error occurs. * * @see #getExportedKeys */ public java.sql.ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { return getCrossReference(null, null, null, catalog, schema, table); } /** * Get a description of a table's indices and statistics. They are ordered * by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION. <P> * * Each index column description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>NON_UNIQUE</B> boolean =>Can index values be non-unique? false * when TYPE is tableIndexStatistic * <LI> <B>INDEX_QUALIFIER</B> String =>index catalog (may be null); null * when TYPE is tableIndexStatistic * <LI> <B>INDEX_NAME</B> String =>index name; null when TYPE is * tableIndexStatistic * <LI> <B>TYPE</B> short =>index type: * <UL> * <LI> tableIndexStatistic - this identifies table statistics that are * returned in conjuction with a table's index descriptions * <LI> tableIndexClustered - this is a clustered index * <LI> tableIndexHashed - this is a hashed index * <LI> tableIndexOther - this is some other style of index * </UL> * * <LI> <B>ORDINAL_POSITION</B> short =>column sequence number within * index; zero when TYPE is tableIndexStatistic * <LI> <B>COLUMN_NAME</B> String =>column name; null when TYPE is * tableIndexStatistic * <LI> <B>ASC_OR_DESC</B> String =>column sort sequence, "A" => * ascending, "D" =>descending, may be null if sort sequence is not * supported; null when TYPE is tableIndexStatistic * <LI> <B>CARDINALITY</B> int =>When TYPE is tableIndexStatistic, then * this is the number of rows in the table; otherwise, it is the number * of unique values in the index. * <LI> <B>PAGES</B> int =>When TYPE is tableIndexStatisic then this is * the number of pages used for the table, otherwise it is the number of * pages used for the current index. * <LI> <B>FILTER_CONDITION</B> String =>Filter condition, if any. (may * be null) * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @param unique when <code>true</code>, return only indices for unique * values; when <code>false</code>, return indices regardless of * whether unique or not * @param approximate when <code>true</code>, result is allowed to reflect * approximate or out of data values; when <code>false</code>, results * are requested to be accurate * @return ResultSet - each row is an index column description * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { String colNames[] = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME", "TYPE", "ORDINAL_POSITION", "COLUMN_NAME", "ASC_OR_DESC", "CARDINALITY", "PAGES", "FILTER_CONDITION"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BIT, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT, Types.SMALLINT, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.VARCHAR}; String query = "sp_statistics ?, ?, ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, table); s.setString(2, schema); s.setString(3, catalog); s.setString(4, "%"); s.setString(5, unique ? "Y" : "N"); s.setString(6, approximate ? "Q" : "E"); JtdsResultSet rs = (JtdsResultSet) s.executeQuery(); int colCnt = rs.getMetaData().getColumnCount(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); while (rs.next()) { for (int i = 1; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } rsTmp.insertRow(); } rs.close(); rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } //---------------------------------------------------------------------- // The following group of methods exposes various limitations // based on the target database with the current driver. // Unless otherwise specified, a result of zero means there is no // limit, or the limit is not known. /** * How many hex characters can you have in an inline binary literal? * * @return max literal length * @throws SQLException if a database-access error occurs. */ public int getMaxBinaryLiteralLength() throws SQLException { // Sybase jConnect says 255 // Actual value is 16384 for Sybase 12.5 // MS JDBC says 0 // Probable maximum size for MS is 65,536 * network packet size return 131072; // per "Programming ODBC for SQLServer" Appendix A } /** * What's the maximum length of a catalog name? * * @return max name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxCatalogNameLength() throws SQLException { return sysnameLength; } /** * What's the max length for a character literal? * * @return max literal length * @throws SQLException if a database-access error occurs. */ public int getMaxCharLiteralLength() throws SQLException { // Sybase jConnect says 255 // Actual value is 16384 for Sybase 12.5 // MS JDBC says 0 // Probable maximum size for MS is 65,536 * network packet size return 131072; // per "Programming ODBC for SQLServer" Appendix A } /** * What's the limit on column name length? * * @return max literal length * @throws SQLException if a database-access error occurs. */ public int getMaxColumnNameLength() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return sysnameLength; } /** * What's the maximum number of columns in a "GROUP BY" clause? * * @return max number of columns * @throws SQLException if a database-access error occurs. */ public int getMaxColumnsInGroupBy() throws SQLException { // Sybase jConnect says 16 // MS JDBC says 16 // per "Programming ODBC for SQLServer" Appendix A // Actual MS value is 8060 / average bytes per column return (tdsVersion >= Driver.TDS70) ? 0 : 16; } /** * What's the maximum number of columns allowed in an index? * * @return max columns * @throws SQLException if a database-access error occurs. */ public int getMaxColumnsInIndex() throws SQLException { // per SQL Server Books Online "Administrator's Companion", // Part 1, Chapter 1. // Sybase 12.5 is 31 return 16; } /** * What's the maximum number of columns in an "ORDER BY" clause? * * @return max columns * @throws SQLException if a database-access error occurs. */ public int getMaxColumnsInOrderBy() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A // Sybase 12.5 is 31 // Actual MS value is 8060 / average bytes per column return (tdsVersion >= Driver.TDS70) ? 0 : 16; } /** * What's the maximum number of columns in a "SELECT" list? * * @return max columns * @throws SQLException if a database-access error occurs. */ public int getMaxColumnsInSelect() throws SQLException { // Sybase jConnect says 0 // per "Programming ODBC for SQLServer" Appendix A return 4096; } /** * What's the maximum number of columns in a table? * * @return max columns * @throws SQLException if a database-access error occurs. */ public int getMaxColumnsInTable() throws SQLException { // Sybase jConnect says 250 // per "Programming ODBC for SQLServer" Appendix A // MS 2000 should be 4096 // Sybase 12.5 is now 1024 return (tdsVersion >= Driver.TDS70) ? 1024 : 250; } /** * How many active connections can we have at a time to this database? * * @return max connections * @throws SQLException if a database-access error occurs. */ public int getMaxConnections() throws SQLException { // Sybase - could query syscurconfigs to get actual value // which in practice will be a lot less than 32767! // per SQL Server Books Online "Administrator's Companion", // Part 1, Chapter 1. return 32767; } /** * What's the maximum cursor name length? * * @return max cursor name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxCursorNameLength() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return sysnameLength; } /** * What's the maximum length of an index (in bytes)? * * @return max index length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxIndexLength() throws SQLException { // Sybase JConnect says 255 // Actual Sybase 12.5 is 600 - 5300 depending on page size // per "Programming ODBC for SQLServer" Appendix A return (tdsVersion >= Driver.TDS70) ? 900 : 255; } /** * What's the maximum length of a procedure name? * * @return max name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxProcedureNameLength() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return sysnameLength; } /** * What's the maximum length of a single row? * * @return max row size in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxRowSize() throws SQLException { // Sybase jConnect says 1962 but this can be more with wide tables. // per SQL Server Books Online "Administrator's Companion", // Part 1, Chapter 1. return (tdsVersion >= Driver.TDS70) ? 8060 : 1962; } /** * What's the maximum length allowed for a schema name? * * @return max name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxSchemaNameLength() throws SQLException { return sysnameLength; } /** * What's the maximum length of a SQL statement? * * @return max length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxStatementLength() throws SQLException { // I think this should return 0 (no limit) // actual limit for SQL 7/2000 is 65536 * packet size! // Sybase JConnect says 0 // MS JDBC says 0 // per "Programming ODBC for SQLServer" Appendix A return 0; } /** * How many active statements can we have open at one time to this * database? * * @return the maximum * @throws SQLException if a database-access error occurs. */ public int getMaxStatements() throws SQLException { return 0; } /** * What's the maximum length of a table name? * * @return max name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxTableNameLength() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return sysnameLength; } /** * What's the maximum number of tables in a SELECT? * * @return the maximum * @throws SQLException if a database-access error occurs. */ public int getMaxTablesInSelect() throws SQLException { // Sybase JConnect says 256 // MS JDBC says 32! // Actual Sybase 12.5 is 50 // per "Programming ODBC for SQLServer" Appendix A return (tdsVersion > Driver.TDS50) ? 256 : 16; } /** * What's the maximum length of a user name? * * @return max name length in bytes * @throws SQLException if a database-access error occurs. */ public int getMaxUserNameLength() throws SQLException { return sysnameLength; } /** * Get a comma separated list of math functions. * * @return the list * @throws SQLException if a database-access error occurs. */ public String getNumericFunctions() throws SQLException { // I don't think either Sybase or SQL have a truncate maths function // so I have removed it from the list. // Also all other drivers return this list in lower case. Should we? return "abs,acos,asin,atan,atan2,ceiling,cos,cot,degrees,exp,floor,log," + "log10,mod,pi,power,radians,rand,round,sign,sin,sqrt,tan"; } /** * Get a description of a table's primary key columns. They are ordered by * COLUMN_NAME. <P> * * Each primary key column description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>COLUMN_NAME</B> String =>column name * <LI> <B>KEY_SEQ</B> short =>sequence number within primary key * <LI> <B>PK_NAME</B> String =>primary key name (may be null) * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @return ResultSet - each row is a primary key column description * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { String colNames[] = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "KEY_SEQ", "PK_NAME"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT, Types.VARCHAR}; String query = "sp_pkeys ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, table); s.setString(2, schema); s.setString(3, catalog); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); while (rs.next()) { for (int i = 1; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } rsTmp.insertRow(); } rs.close(); rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } /** * Get a description of a catalog's stored procedure parameters and result * columns. <P> * * Only descriptions matching the schema, procedure and parameter name * criteria are returned. They are ordered by PROCEDURE_SCHEM and * PROCEDURE_NAME. Within this, the return value, if any, is first. Next * are the parameter descriptions in call order. The column descriptions * follow in column number order. <P> * * Each row in the ResultSet is a parameter description or column * description with the following fields: * <OL> * <LI> <B>PROCEDURE_CAT</B> String =>procedure catalog (may be null) * * <LI> <B>PROCEDURE_SCHEM</B> String =>procedure schema (may be null) * * <LI> <B>PROCEDURE_NAME</B> String =>procedure name * <LI> <B>COLUMN_NAME</B> String =>column/parameter name * <LI> <B>COLUMN_TYPE</B> Short =>kind of column/parameter: * <UL> * <LI> procedureColumnUnknown - nobody knows * <LI> procedureColumnIn - IN parameter * <LI> procedureColumnInOut - INOUT parameter * <LI> procedureColumnOut - OUT parameter * <LI> procedureColumnReturn - procedure return value * <LI> procedureColumnResult - result column in ResultSet * </UL> * * <LI> <B>DATA_TYPE</B> short =>SQL type from java.sql.Types * <LI> <B>TYPE_NAME</B> String =>SQL type name * <LI> <B>PRECISION</B> int =>precision * <LI> <B>LENGTH</B> int =>length in bytes of data * <LI> <B>SCALE</B> short =>scale * <LI> <B>RADIX</B> short =>radix * <LI> <B>NULLABLE</B> short =>can it contain NULL? * <UL> * <LI> procedureNoNulls - does not allow NULL values * <LI> procedureNullable - allows NULL values * <LI> procedureNullableUnknown - nullability unknown * </UL> * * <LI> <B>REMARKS</B> String =>comment describing parameter/column * </OL> * <P> * * <B>Note:</B> Some databases may not return the column descriptions for a * procedure. Additional columns beyond REMARKS can be defined by the * database. * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param procedureNamePattern a procedure name pattern * @param columnNamePattern a column name pattern * @return ResultSet - each row is a stored procedure parameter or column description * @throws SQLException if a database-access error occurs. * @see #getSearchStringEscape */ public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { String colNames[] = {"PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME", "COLUMN_NAME", "COLUMN_TYPE", "DATA_TYPE", "TYPE_NAME", "PRECISION", "LENGTH", "SCALE", "RADIX", "NULLABLE", "REMARKS"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.SMALLINT, Types.SMALLINT, Types.SMALLINT, Types.VARCHAR}; String query = "sp_sproc_columns ?, ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog,query)); s.setString(1, processEscapes(procedureNamePattern)); s.setString(2, processEscapes(schemaPattern)); s.setString(3, catalog); s.setString(4, processEscapes(columnNamePattern)); s.setInt(5, 3); // ODBC version 3 JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); while (rs.next()) { int offset = 0; for (int i = 1; i + offset <= colNames.length; i++) { if (i == 5 && !"column_type".equalsIgnoreCase(rsmd.getColumnName(i))) { // With Sybase 11.92 despite what the documentation says, the // column_type column is missing! // Set the output value to 0 and shift the rest along by one. String colName = rs.getString(4); if ("RETURN_VALUE".equals(colName)) { rsTmp.updateInt(i, DatabaseMetaData.procedureColumnReturn); } else { rsTmp.updateInt(i, DatabaseMetaData.procedureColumnUnknown); } offset = 1; } if (i == 3) { String name = rs.getString(i); if (name != null && name.length() > 0) { int pos = name.lastIndexOf(';'); if (pos >= 0) { name = name.substring(0, pos); } } rsTmp.updateString(i + offset, name); } else if ("data_type".equalsIgnoreCase(rsmd.getColumnName(i))) { int type = TypeInfo.normalizeDataType(rs.getInt(i), connection.getUseLOBs()); rsTmp.updateInt(i + offset, type); } else { rsTmp.updateObject(i + offset, rs.getObject(i)); } } if (serverType == Driver.SYBASE && rsmd.getColumnCount() >= 22) { // // For Sybase 12.5+ we can obtain column in/out status from // the mode column. // String mode = rs.getString(22); if (mode != null) { if (mode.equalsIgnoreCase("in")) { rsTmp.updateInt(5, DatabaseMetaData.procedureColumnIn); } else if (mode.equalsIgnoreCase("out")) { rsTmp.updateInt(5, DatabaseMetaData.procedureColumnInOut); } } } if (serverType == Driver.SYBASE || tdsVersion == Driver.TDS42 || tdsVersion == Driver.TDS70) { // // Standardise the name of the return_value column as // @RETURN_VALUE for Sybase and SQL < 2000 // String colName = rs.getString(4); if ("RETURN_VALUE".equals(colName)) { rsTmp.updateString(4, "@RETURN_VALUE"); } } rsTmp.insertRow(); } rs.close(); rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rsTmp; } /** * Get a description of stored procedures available in a catalog. <P> * * Only procedure descriptions matching the schema and procedure name * criteria are returned. They are ordered by PROCEDURE_SCHEM, and * PROCEDURE_NAME. <P> * * Each procedure description has the the following columns: * <OL> * <LI> <B>PROCEDURE_CAT</B> String =>procedure catalog (may be null) * * <LI> <B>PROCEDURE_SCHEM</B> String =>procedure schema (may be null) * * <LI> <B>PROCEDURE_NAME</B> String =>procedure name * <LI> reserved for future use * <LI> reserved for future use * <LI> reserved for future use * <LI> <B>REMARKS</B> String =>explanatory comment on the procedure * <LI> <B>PROCEDURE_TYPE</B> short =>kind of procedure: * <UL> * <LI> procedureResultUnknown - May return a result * <LI> procedureNoResult - Does not return a result * <LI> procedureReturnsResult - Returns a result * </UL> * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param procedureNamePattern a procedure name pattern * @return ResultSet - each row is a procedure description * @throws SQLException if a database-access error occurs. * * @see #getSearchStringEscape */ public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { String colNames[] = {"PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME", "RESERVED_1", "RESERVED_2", "RESERVED_3", "REMARKS", "PROCEDURE_TYPE"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.SMALLINT}; String query = "sp_stored_procedures ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, processEscapes(procedureNamePattern)); s.setString(2, processEscapes(schemaPattern)); s.setString(3, catalog); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); // // Copy results to local result set. // while (rs.next()) { rsTmp.updateString(1, rs.getString(1)); rsTmp.updateString(2, rs.getString(2)); String name = rs.getString(3); if (name != null) { // Remove grouping integer if (name.endsWith(";1")) { name = name.substring(0, name.length() - 2); } } rsTmp.updateString(3, name); // Copy over rest of fields for (int i = 4; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } if (colCnt < 8) { // Sybase does not return this column so fake it now. rsTmp.updateShort(8, (short)DatabaseMetaData.procedureReturnsResult); } rsTmp.insertRow(); } rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); rs.close(); return rsTmp; } /** * What's the database vendor's preferred term for "procedure"? * * @return the vendor term * @throws SQLException if a database-access error occurs. */ public String getProcedureTerm() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return "stored procedure"; } /** * Get the schema names available in this database. The results are ordered * by schema name. <P> * * The schema column is: * <OL> * <LI> <B>TABLE_SCHEM</B> String => schema name * <LI> <B>TABLE_CATALOG</B> String => catalog name (may be <code>null</code>, JDBC 3.0) * </OL> * * @return a <code>ResultSet</code> object in which each row is a schema description * @throws SQLException if a database access error occurs */ public java.sql.ResultSet getSchemas() throws SQLException { java.sql.Statement statement = connection.createStatement(); String sql; if (connection.getServerType() == Driver.SQLSERVER && connection.getDatabaseMajorVersion() >= 9) { sql = "SELECT name AS TABLE_SCHEM, NULL as TABLE_CATALOG FROM sys.schemas"; } else { sql = "SELECT name AS TABLE_SCHEM, NULL as TABLE_CATALOG FROM dbo.sysusers"; // // MJH - isLogin column only in MSSQL >= 7.0 // if (tdsVersion >= Driver.TDS70) { sql += " WHERE islogin=1"; } else { sql += " WHERE uid>0"; } } sql += " ORDER BY TABLE_SCHEM"; return statement.executeQuery(sql); } /** * What's the database vendor's preferred term for "schema"? * * @return the vendor term * @throws SQLException if a database-access error occurs. */ public String getSchemaTerm() throws SQLException { return "owner"; } /** * This is the string that can be used to escape '_' or '%' in the string * pattern style catalog search parameters. <P> * * The '_' character represents any single character. <P> * * The '%' character represents any sequence of zero or more characters. * * @return the string used to escape wildcard characters * @throws SQLException if a database-access error occurs. */ public String getSearchStringEscape() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return "\\"; } /** * Get a comma separated list of all a database's SQL keywords that are NOT * also SQL92 keywords. * * @return the list * @throws SQLException if a database-access error occurs. */ public String getSQLKeywords() throws SQLException { // // This is a superset of the SQL keywords in SQL Server and Sybase // return "ARITH_OVERFLOW,BREAK,BROWSE,BULK,CHAR_CONVERT,CHECKPOINT," + "CLUSTERED,COMPUTE,CONFIRM,CONTROLROW,DATA_PGS,DATABASE,DBCC," + "DISK,DUMMY,DUMP,ENDTRAN,ERRLVL,ERRORDATA,ERROREXIT,EXIT," + "FILLFACTOR,HOLDLOCK,IDENTITY_INSERT,IF,INDEX,KILL,LINENO," + "LOAD,MAX_ROWS_PER_PAGE,MIRROR,MIRROREXIT,NOHOLDLOCK,NONCLUSTERED," + "NUMERIC_TRUNCATION,OFF,OFFSETS,ONCE,ONLINE,OVER,PARTITION,PERM," + "PERMANENT,PLAN,PRINT,PROC,PROCESSEXIT,RAISERROR,READ,READTEXT," + "RECONFIGURE,REPLACE,RESERVED_PGS,RETURN,ROLE,ROWCNT,ROWCOUNT," + "RULE,SAVE,SETUSER,SHARED,SHUTDOWN,SOME,STATISTICS,STRIPE," + "SYB_IDENTITY,SYB_RESTREE,SYB_TERMINATE,TEMP,TEXTSIZE,TRAN," + "TRIGGER,TRUNCATE,TSEQUAL,UNPARTITION,USE,USED_PGS,USER_OPTION," + "WAITFOR,WHILE,WRITETEXT"; } /** * Get a comma separated list of string functions. * * @return the list * @throws SQLException if a database-access error occurs. */ public String getStringFunctions() throws SQLException { if (connection.getServerType() == Driver.SQLSERVER) { return "ascii,char,concat,difference,insert,lcase,left,length,locate," + "ltrim,repeat,replace,right,rtrim,soundex,space,substring,ucase"; } else { return "ascii,char,concat,difference,insert,lcase,length," + "ltrim,repeat,right,rtrim,soundex,space,substring,ucase"; } } /** * Get a comma separated list of system functions. * * @return the list * @throws SQLException if a database-access error occurs. */ public String getSystemFunctions() throws SQLException { return "database,ifnull,user,convert"; } /** * Get a description of the access rights for each table available in a * catalog. Note that a table privilege applies to one or more columns in * the table. It would be wrong to assume that this priviledge applies to * all columns (this may be true for some systems but is not true for all.) * <P> * * Only privileges matching the schema and table name criteria are * returned. They are ordered by TABLE_SCHEM, TABLE_NAME, and PRIVILEGE. * <P> * * Each privilige description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>GRANTOR</B> =>grantor of access (may be null) * <LI> <B>GRANTEE</B> String =>grantee of access * <LI> <B>PRIVILEGE</B> String =>name of access (SELECT, INSERT, UPDATE, * REFRENCES, ...) * <LI> <B>IS_GRANTABLE</B> String =>"YES" if grantee is permitted to * grant to others; "NO" if not; null if unknown * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param tableNamePattern a table name pattern * @return ResultSet - each row is a table privilege description * @throws SQLException if a database-access error occurs. * * @see #getSearchStringEscape */ public java.sql.ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { String query = "sp_table_privileges ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, processEscapes(tableNamePattern)); s.setString(2, processEscapes(schemaPattern)); s.setString(3, catalog); JtdsResultSet rs = (JtdsResultSet)s.executeQuery(); rs.setColLabel(1, "TABLE_CAT"); rs.setColLabel(2, "TABLE_SCHEM"); upperCaseColumnNames(rs); return rs; } /** * Get a description of tables available in a catalog. <P> * * Only table descriptions matching the catalog, schema, table name and * type criteria are returned. They are ordered by TABLE_TYPE, TABLE_SCHEM * and TABLE_NAME. <P> * * Each table description has the following columns: * <OL> * <LI> <B>TABLE_CAT</B> String =>table catalog (may be null) * <LI> <B>TABLE_SCHEM</B> String =>table schema (may be null) * <LI> <B>TABLE_NAME</B> String =>table name * <LI> <B>TABLE_TYPE</B> String =>table type. Typical types are "TABLE", * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", * "ALIAS", "SYNONYM". * <LI> <B>REMARKS</B> String =>explanatory comment on the table * <LI> <B>TYPE_CAT</B> String => the types catalog (may be * <code>null</code>) * <LI> <B>TYPE_SCHEM</B> String => the types schema (may be * <code>null</code>) * <LI> <B>TYPE_NAME</B> String => type name (may be <code>null</code>) * <LI> <B>SELF_REFERENCING_COL_NAME</B> String => name of the designated * "identifier" column of a typed table (may be <code>null</code>) * <LI> <B>REF_GENERATION</B> String => specifies how values in * SELF_REFERENCING_COL_NAME are created. Values are "SYSTEM", "USER", * "DERIVED". (may be <code>null</code>) * </OL> * <P> * * <B>Note:</B> Some databases may not return information for all tables. * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param tableNamePattern a table name pattern * @param types a list of table types to include; null returns all types * @return ResultSet - each row is a table description * @throws SQLException if a database-access error occurs. * * @see #getSearchStringEscape */ public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException { String colNames[] = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR}; String query = "sp_tables ?, ?, ?, ?"; CallableStatement cstmt = connection.prepareCall(syscall(catalog, query)); cstmt.setString(1, processEscapes(tableNamePattern)); cstmt.setString(2, processEscapes(schemaPattern)); cstmt.setString(3, catalog); if (types == null) { cstmt.setString(4, null); } else { StringBuilder buf = new StringBuilder(64); buf.append('"'); for (int i = 0; i < types.length; i++) { buf.append('\'').append(types[i]).append("',"); } if (buf.length() > 1) { buf.setLength(buf.length() - 1); } buf.append('"'); cstmt.setString(4, buf.toString()); } JtdsResultSet rs = (JtdsResultSet) cstmt.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)cstmt, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); // // Copy results to local result set. // while (rs.next()) { for (int i = 1; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } rsTmp.insertRow(); } rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); rs.close(); return rsTmp; } /** * Get the table types available in this database. The results are ordered * by table type. <P> * * The table type is: * <OL> * <LI> <B>TABLE_TYPE</B> String => table type. Typical types are "TABLE", * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", * "ALIAS", "SYNONYM". * </OL> * * @return ResultSet - each row has a single String column that is a table type * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getTableTypes() throws SQLException { String sql = "select 'SYSTEM TABLE' TABLE_TYPE " + "union select 'TABLE' TABLE_TYPE " + "union select 'VIEW' TABLE_TYPE " + "order by TABLE_TYPE"; java.sql.Statement stmt = connection.createStatement(); return stmt.executeQuery(sql); } /** * Get a comma separated list of time and date functions. * * @return the list * @throws SQLException if a database-access error occurs. */ public String getTimeDateFunctions() throws SQLException { return "curdate,curtime,dayname,dayofmonth,dayofweek,dayofyear,hour," + "minute,month,monthname,now,quarter,timestampadd,timestampdiff," + "second,week,year"; } /** * Get a description of all the standard SQL types supported by this * database. They are ordered by DATA_TYPE and then by how closely the data * type maps to the corresponding JDBC SQL type. <P> * * Each type description has the following columns: * <OL> * <LI> <B>TYPE_NAME</B> String =>Type name * <LI> <B>DATA_TYPE</B> short =>SQL data type from java.sql.Types * <LI> <B>PRECISION</B> int =>maximum precision * <LI> <B>LITERAL_PREFIX</B> String =>prefix used to quote a literal * (may be null) * <LI> <B>LITERAL_SUFFIX</B> String =>suffix used to quote a literal * (may be null) * <LI> <B>CREATE_PARAMS</B> String =>parameters used in creating the * type (may be null) * <LI> <B>NULLABLE</B> short =>can you use NULL for this type? * <UL> * <LI> typeNoNulls - does not allow NULL values * <LI> typeNullable - allows NULL values * <LI> typeNullableUnknown - nullability unknown * </UL> * * <LI> <B>CASE_SENSITIVE</B> boolean=>is it case sensitive? * <LI> <B>SEARCHABLE</B> short =>can you use "WHERE" based on this type: * * <UL> * <LI> typePredNone - No support * <LI> typePredChar - Only supported with WHERE .. LIKE * <LI> typePredBasic - Supported except for WHERE .. LIKE * <LI> typeSearchable - Supported for all WHERE .. * </UL> * * <LI> <B>UNSIGNED_ATTRIBUTE</B> boolean =>is it unsigned? * <LI> <B>FIXED_PREC_SCALE</B> boolean =>can it be a money value? * <LI> <B>AUTO_INCREMENT</B> boolean =>can it be used for an * auto-increment value? * <LI> <B>LOCAL_TYPE_NAME</B> String =>localized version of type name * (may be null) * <LI> <B>MINIMUM_SCALE</B> short =>minimum scale supported * <LI> <B>MAXIMUM_SCALE</B> short =>maximum scale supported * <LI> <B>SQL_DATA_TYPE</B> int =>unused * <LI> <B>SQL_DATETIME_SUB</B> int =>unused * <LI> <B>NUM_PREC_RADIX</B> int =>usually 2 or 10 * </OL> * * @return ResultSet - each row is a SQL type description * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getTypeInfo() throws SQLException { Statement s = connection.createStatement(); JtdsResultSet rs; try { rs = (JtdsResultSet) s.executeQuery("exec sp_datatype_info @ODBCVer=3"); } catch (SQLException ex) { s.close(); throw ex; } try { return createTypeInfoResultSet(rs, connection.getUseLOBs()); } finally { // CachedResultSet retains reference to same statement as rs, so don't close statement rs.close(); } } /** * JDBC 2.0 Gets a description of the user-defined types defined in a * particular schema. Schema-specific UDTs may have type JAVA_OBJECT, * STRUCT, or DISTINCT. <P> * * Only types matching the catalog, schema, type name and type criteria are * returned. They are ordered by DATA_TYPE, TYPE_SCHEM and TYPE_NAME. The * type name parameter may be a fully-qualified name. In this case, the * catalog and schemaPattern parameters are ignored. <P> * * Each type description has the following columns: * <OL> * <LI> <B>TYPE_CAT</B> String =>the type's catalog (may be null) * <LI> <B>TYPE_SCHEM</B> String =>type's schema (may be null) * <LI> <B>TYPE_NAME</B> String =>type name * <LI> <B>CLASS_NAME</B> String =>Java class name * <LI> <B>DATA_TYPE</B> String =>type value defined in java.sql.Types. * One of JAVA_OBJECT, STRUCT, or DISTINCT * <LI> <B>REMARKS</B> String =>explanatory comment on the type * </OL> * <P> * * <B>Note:</B> If the driver does not support UDTs, an empty result set is * returned. * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param typeNamePattern a type name pattern; may be a fully-qualified * name * @param types a list of user-named types to include * (JAVA_OBJECT, STRUCT, or DISTINCT); null returns all types * @return ResultSet - each row is a type description * @throws SQLException if a database access error occurs */ public java.sql.ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { String colNames[] = {"TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "CLASS_NAME", "DATA_TYPE", "REMARKS", "BASE_TYPE"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.SMALLINT}; // // Return an empty result set // JtdsStatement dummyStmt = (JtdsStatement) connection.createStatement(); CachedResultSet rs = new CachedResultSet(dummyStmt, colNames, colTypes); rs.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rs; } /** * What's the URL for this database? * * @return the URL or null if it can't be generated * @throws SQLException if a database-access error occurs */ public String getURL() throws SQLException { return connection.getURL(); } /** * What's our user name as known to the database? * * @return our database user name * @throws SQLException if a database-access error occurs. */ public String getUserName() throws SQLException { java.sql.Statement s = null; java.sql.ResultSet rs = null; String result = ""; try { s = connection.createStatement(); // MJH Sybase does not support system_user if (connection.getServerType() == Driver.SYBASE) { rs = s.executeQuery("select suser_name()"); } else { rs = s.executeQuery("select system_user"); } if (!rs.next()) { throw new SQLException(Messages.get("error.dbmeta.nouser"), "HY000"); } result = rs.getString(1); } finally { if (rs != null) { rs.close(); } if (s != null) { s.close(); } } return result; } /** * Get a description of a table's columns that are automatically updated * when any value in a row is updated. They are unordered. <P> * * Each column description has the following columns: * <OL> * <LI> <B>SCOPE</B> short =>is not used * <LI> <B>COLUMN_NAME</B> String =>column name * <LI> <B>DATA_TYPE</B> short =>SQL data type from java.sql.Types * <LI> <B>TYPE_NAME</B> String =>Data source dependent type name * <LI> <B>COLUMN_SIZE</B> int =>precision * <LI> <B>BUFFER_LENGTH</B> int =>length of column value in bytes * <LI> <B>DECIMAL_DIGITS</B> short =>scale * <LI> <B>PSEUDO_COLUMN</B> short =>is this a pseudo column like an * Oracle ROWID * <UL> * <LI> versionColumnUnknown - may or may not be pseudo column * <LI> versionColumnNotPseudo - is NOT a pseudo column * <LI> versionColumnPseudo - is a pseudo column * </UL> * </OL> * * @param catalog a catalog name; "" retrieves those without a * <code>null</code> means drop catalog name from the selection criteria * @param schema a schema name; "" retrieves those without a schema * @param table a table name * @return ResultSet - each row is a column description * @throws SQLException if a database-access error occurs. */ public java.sql.ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { String colNames[] = {"SCOPE", "COLUMN_NAME","DATA_TYPE", "TYPE_NAME","COLUMN_SIZE", "BUFFER_LENGTH","DECIMAL_DIGITS", "PSEUDO_COLUMN"}; int colTypes[] = {Types.SMALLINT,Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.SMALLINT,Types.SMALLINT}; String query = "sp_special_columns ?, ?, ?, ?, ?, ?, ?"; CallableStatement s = connection.prepareCall(syscall(catalog, query)); s.setString(1, table); s.setString(2, schema); s.setString(3, catalog); s.setString(4, "V"); s.setString(5, "C"); s.setString(6, "O"); s.setInt(7, 3); // ODBC version 3 JtdsResultSet rs = (JtdsResultSet) s.executeQuery(); CachedResultSet rsTmp = new CachedResultSet((JtdsStatement)s, colNames, colTypes); rsTmp.moveToInsertRow(); int colCnt = rs.getMetaData().getColumnCount(); // // Copy results to local result set. // while (rs.next()) { for (int i = 1; i <= colCnt; i++) { rsTmp.updateObject(i, rs.getObject(i)); } rsTmp.insertRow(); } rsTmp.moveToCurrentRow(); rsTmp.setConcurrency(ResultSet.CONCUR_READ_ONLY); rs.close(); return rsTmp; } /** * Retrieves whether a catalog appears at the start of a fully qualified * table name. If not, the catalog appears at the end. * * @return true if it appears at the start * @throws SQLException if a database-access error occurs. */ public boolean isCatalogAtStart() throws SQLException { return true; } /** * Is the database in read-only mode? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean isReadOnly() throws SQLException { return false; } /** * JDBC 2.0 Retrieves the connection that produced this metadata object. * * @return the connection that produced this metadata object * @throws SQLException if a database-access error occurs. */ public java.sql.Connection getConnection() throws SQLException { return connection; } /** * Retrieves whether this database supports concatenations between * <code>NULL</code> and non-<code>NULL</code> values being * <code>NULL</code>. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean nullPlusNonNullIsNull() throws SQLException { // Sybase 11.92 says true // MS SQLServer seems to break with the SQL standard here. // maybe there is an option to make null behavior comply // // SAfe: Nope, it seems to work fine in SQL Server 7.0 return true; } /** * Are NULL values sorted at the end regardless of sort order? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean nullsAreSortedAtEnd() throws SQLException { return false; } /** * Are NULL values sorted at the start regardless of sort order? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean nullsAreSortedAtStart() throws SQLException { return false; } /** * Are NULL values sorted high? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean nullsAreSortedHigh() throws SQLException { return false; } /** * Are NULL values sorted low? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean nullsAreSortedLow() throws SQLException { return true; } /** * Does the database treat mixed case unquoted SQL identifiers as case * insensitive and store them in lower case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesLowerCaseIdentifiers() throws SQLException { return false; } /** * Does the database treat mixed case quoted SQL identifiers as case * insensitive and store them in lower case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { return false; } /** * Does the database treat mixed case unquoted SQL identifiers as case * insensitive and store them in mixed case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesMixedCaseIdentifiers() throws SQLException { setCaseSensitiveFlag(); return !caseSensitive.booleanValue(); } /** * Does the database treat mixed case quoted SQL identifiers as case * insensitive and store them in mixed case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { setCaseSensitiveFlag(); return !caseSensitive.booleanValue(); } /** * Does the database treat mixed case unquoted SQL identifiers as case * insensitive and store them in upper case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesUpperCaseIdentifiers() throws SQLException { return false; } /** * Does the database treat mixed case quoted SQL identifiers as case * insensitive and store them in upper case? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { return false; } //-------------------------------------------------------------------- // Functions describing which features are supported. /** * Is "ALTER TABLE" with add column supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsAlterTableWithAddColumn() throws SQLException { return true; } /** * Is "ALTER TABLE" with drop column supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsAlterTableWithDropColumn() throws SQLException { return true; } /** * Retrieves whether this database supports the ANSI92 entry level SQL * grammar. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsANSI92EntryLevelSQL() throws SQLException { return true; } /** * Is the ANSI92 full SQL grammar supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsANSI92FullSQL() throws SQLException { return false; } /** * Is the ANSI92 intermediate SQL grammar supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsANSI92IntermediateSQL() throws SQLException { return false; } /** * Can a catalog name be used in a data manipulation statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCatalogsInDataManipulation() throws SQLException { return true; } /** * Can a catalog name be used in an index definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCatalogsInIndexDefinitions() throws SQLException { return true; } /** * Can a catalog name be used in a privilege definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { return true; } /** * Can a catalog name be used in a procedure call statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCatalogsInProcedureCalls() throws SQLException { return true; } /** * Can a catalog name be used in a table definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCatalogsInTableDefinitions() throws SQLException { return true; } /** * Retrieves whether this database supports column aliasing. * <p> * If so, the SQL AS clause can be used to provide names for computed * columns or to provide alias names for columns as required. A * JDBC-Compliant driver always returns true. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsColumnAliasing() throws SQLException { return true; } /** * Is the CONVERT function between SQL types supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsConvert() throws SQLException { return true; } /** * Is CONVERT between the given SQL types supported? * * @param fromType the type to convert from * @param toType the type to convert to * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsConvert(int fromType, int toType) throws SQLException { if (fromType == toType) { return true; } switch (fromType) { // SAfe Most types will convert to anything but IMAGE and // TEXT/NTEXT (and UNIQUEIDENTIFIER, but that's not a standard // type). case Types.BIT: case Types.TINYINT: case Types.SMALLINT: case Types.INTEGER: case Types.BIGINT: case Types.FLOAT: case Types.REAL: case Types.DOUBLE: case Types.NUMERIC: case Types.DECIMAL: case Types.DATE: case Types.TIME: case Types.TIMESTAMP: return toType != Types.LONGVARCHAR && toType != Types.LONGVARBINARY && toType != Types.BLOB && toType != Types.CLOB; case Types.BINARY: case Types.VARBINARY: return toType != Types.FLOAT && toType != Types.REAL && toType != Types.DOUBLE; // IMAGE case Types.BLOB: case Types.LONGVARBINARY: return toType == Types.BINARY || toType == Types.VARBINARY || toType == Types.BLOB || toType == Types.LONGVARBINARY; // TEXT and NTEXT case Types.CLOB: case Types.LONGVARCHAR: return toType == Types.CHAR || toType == Types.VARCHAR || toType == Types.CLOB || toType == Types.LONGVARCHAR; // These types can be converted to anything case Types.NULL: case Types.CHAR: case Types.VARCHAR: return true; // We can't tell for sure what will happen with other types, so... case Types.OTHER: default: return false; } } /** * Is the ODBC Core SQL grammar supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCoreSQLGrammar() throws SQLException { return true; } /** * Retrieves whether this database supports correlated subqueries. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsCorrelatedSubqueries() throws SQLException { return true; } /** * Are both data definition and data manipulation statements within a * transaction supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { // Sybase requires the 'DDL IN TRAN' db option to be set for // This to be strictly true. return true; } /** * Are only data manipulation statements within a transaction supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsDataManipulationTransactionsOnly() throws SQLException { return false; } /** * If table correlation names are supported, are they restricted to be * different from the names of the tables? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsDifferentTableCorrelationNames() throws SQLException { return false; } /** * Are expressions in "ORDER BY" lists supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsExpressionsInOrderBy() throws SQLException { return true; } /** * Is the ODBC Extended SQL grammar supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsExtendedSQLGrammar() throws SQLException { return false; } /** * Are full nested outer joins supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsFullOuterJoins() throws SQLException { if (connection.getServerType() == Driver.SYBASE) { // Supported since version 12 return getDatabaseMajorVersion() >= 12; } return true; } /** * Is some form of "GROUP BY" clause supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsGroupBy() throws SQLException { return true; } /** * Can a "GROUP BY" clause add columns not in the SELECT provided it * specifies all the columns in the SELECT? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsGroupByBeyondSelect() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return true; } /** * Can a "GROUP BY" clause use columns not in the SELECT? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsGroupByUnrelated() throws SQLException { return true; } /** * Is the SQL Integrity Enhancement Facility supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsIntegrityEnhancementFacility() throws SQLException { return false; } /** * Retrieves whether this database supports specifying a <code>LIKE</code> * escape clause. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsLikeEscapeClause() throws SQLException { // per "Programming ODBC for SQLServer" Appendix A return true; } /** * Retrieves whether this database provides limited support for outer * joins. (This will be <code>true</code> if the method * <code>supportsFullOuterJoins</code> returns <code>true</code>). * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsLimitedOuterJoins() throws SQLException { return true; } /** * Retrieves whether this database supports the ODBC Minimum SQL grammar. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsMinimumSQLGrammar() throws SQLException { return true; } /** * Retrieves whether this database treats mixed case unquoted SQL identifiers as * case sensitive and as a result stores them in mixed case. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsMixedCaseIdentifiers() throws SQLException { setCaseSensitiveFlag(); return caseSensitive.booleanValue(); } /** * Retrieves whether this database treats mixed case quoted SQL identifiers as * case sensitive and as a result stores them in mixed case. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { setCaseSensitiveFlag(); return caseSensitive.booleanValue(); } /** * Are multiple ResultSets from a single execute supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsMultipleResultSets() throws SQLException { return true; } /** * Can we have multiple transactions open at once (on different * connections)? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsMultipleTransactions() throws SQLException { return true; } /** * Retrieves whether columns in this database may be defined as non-nullable. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsNonNullableColumns() throws SQLException { return true; } /** * Can cursors remain open across commits? * * @return <code>true</code> if cursors always remain open; * <code>false</code> if they might not remain open * @throws SQLException if a database-access error occurs. */ public boolean supportsOpenCursorsAcrossCommit() throws SQLException { // MS JDBC says false return true; } /** * Can cursors remain open across rollbacks? * * @return <code>true</code> if cursors always remain open; * <code>false</code> if they might not remain open * @throws SQLException if a database-access error occurs. */ public boolean supportsOpenCursorsAcrossRollback() throws SQLException { // JConnect says true return connection.getServerType() == Driver.SYBASE; } /** * Can statements remain open across commits? * * @return <code>true</code> if statements always remain open; * <code>false</code> if they might not remain open * @throws SQLException if a database-access error occurs. */ public boolean supportsOpenStatementsAcrossCommit() throws SQLException { return true; } /** * Can statements remain open across rollbacks? * * @return <code>true</code> if statements always remain open; * <code>false</code> if they might not remain open * @throws SQLException if a database-access error occurs. */ public boolean supportsOpenStatementsAcrossRollback() throws SQLException { return true; } /** * Can an "ORDER BY" clause use columns not in the SELECT? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsOrderByUnrelated() throws SQLException { return true; } /** * Is some form of outer join supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsOuterJoins() throws SQLException { return true; } /** * Is positioned DELETE supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsPositionedDelete() throws SQLException { return true; } /** * Is positioned UPDATE supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsPositionedUpdate() throws SQLException { return true; } /** * Can a schema name be used in a data manipulation statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSchemasInDataManipulation() throws SQLException { return true; } /** * Can a schema name be used in an index definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSchemasInIndexDefinitions() throws SQLException { return true; } /** * Can a schema name be used in a privilege definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { return true; } /** * Can a schema name be used in a procedure call statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSchemasInProcedureCalls() throws SQLException { return true; } /** * Can a schema name be used in a table definition statement? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSchemasInTableDefinitions() throws SQLException { return true; } /** * Is SELECT for UPDATE supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSelectForUpdate() throws SQLException { // XXX Server supports it driver doesn't currently // As far as I know the SQL Server FOR UPDATE is not the same as the // standard SQL FOR UPDATE return false; } /** * Are stored procedure calls using the stored procedure escape syntax * supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsStoredProcedures() throws SQLException { return true; } /** * Retrieves whether this database supports subqueries in comparison * expressions. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSubqueriesInComparisons() throws SQLException { return true; } /** * Retrieves whether this database supports subqueries in * <code>EXISTS</code> expressions. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSubqueriesInExists() throws SQLException { return true; } /** * Retrieves whether this database supports subqueries in * <code>IN</code> statements. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSubqueriesInIns() throws SQLException { return true; } /** * Retrieves whether this database supports subqueries in quantified * expressions. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsSubqueriesInQuantifieds() throws SQLException { return true; } /** * Retrieves whether this database supports table correlation names. * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsTableCorrelationNames() throws SQLException { return true; } /** * Does the database support the given transaction isolation level? * * @param level the values are defined in java.sql.Connection * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. * * @see Connection */ public boolean supportsTransactionIsolationLevel(int level) throws SQLException { switch (level) { case Connection.TRANSACTION_READ_UNCOMMITTED: case Connection.TRANSACTION_READ_COMMITTED: case Connection.TRANSACTION_REPEATABLE_READ: case Connection.TRANSACTION_SERIALIZABLE: return true; // TRANSACTION_NONE not supported. It means there is no support for // transactions case Connection.TRANSACTION_NONE: default: return false; } } /** * Retrieves whether this database supports transactions. If not, invoking the * method <code>commit</code> is a noop, and the isolation level is * <code>TRANSACTION_NONE</code>. * * @return <code>true</code> if transactions are supported * @throws SQLException if a database-access error occurs. */ public boolean supportsTransactions() throws SQLException { return true; } /** * Is SQL UNION supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsUnion() throws SQLException { return true; } /** * Is SQL UNION ALL supported? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean supportsUnionAll() throws SQLException { return true; } /** * Does the database use a file for each table? * * @return <code>true</code> if the database uses a local file for each * table * @throws SQLException if a database-access error occurs. */ public boolean usesLocalFilePerTable() throws SQLException { return false; } /** * Does the database store tables in a local file? * * @return <code>true</code> if so * @throws SQLException if a database-access error occurs. */ public boolean usesLocalFiles() throws SQLException { return false; } //--------------------------JDBC 2.0----------------------------- /** * Does the database support the given result set type? * <p/> * Supported types for SQL Server: * <table> * <tr> * <td valign="top">JDBC type</td> * <td valign="top">SQL Server cursor type</td> * <td valign="top">Server load</td> * <td valign="top">Description</td> * </tr> * <tr> * <td valign="top">TYPE_FORWARD_ONLY</td> * <td valign="top">Forward-only, dynamic (fast forward-only, static with <code>useCursors=true</code>)</td> * <td valign="top">Light</td> * <td valign="top">Fast, will read all data (less fast, doesn't read all data with <code>useCursors=true</code>). Forward only.</td> * </tr> * <tr> * <td valign="top">TYPE_SCROLL_INSENSITIVE</td> * <td valign="top">Static cursor</td> * <td valign="top">Heavy</td> * <td valign="top">Only use with CONCUR_READ_ONLY. SQL Server generates a temporary table, so changes made by others are not visible. Scrollable.</td> * </tr> * <tr> * <td valign="top">TYPE_SCROLL_SENSITIVE</td> * <td valign="top">Keyset cursor</td> * <td valign="top">Medium</td> * <td valign="top">Others' updates or deletes visible, but not others' inserts. Scrollable.</td> * </tr> * <tr> * <td valign="top">TYPE_SCROLL_SENSITIVE + 1</td> * <td valign="top">Dynamic cursor</td> * <td valign="top">Heavy</td> * <td valign="top">Others' updates, deletes and inserts visible. Scrollable.</td> * </tr> * </table> * * @param type defined in <code>java.sql.ResultSet</code> * @return <code>true</code> if so; <code>false</code> otherwise * @throws SQLException if a database access error occurs * * @see Connection * @see #supportsResultSetConcurrency */ public boolean supportsResultSetType(int type) throws SQLException { // jTDS supports all standard ResultSet types plus // TYPE_SCROLL_SENSITIVE + 1 return type >= ResultSet.TYPE_FORWARD_ONLY && type <= ResultSet.TYPE_SCROLL_SENSITIVE + 1; } /** * Does the database support the concurrency type in combination with the * given result set type? * <p/> * Supported concurrencies for SQL Server: * <table> * <tr> * <td>JDBC concurrency</td> * <td>SQL Server concurrency</td> * <td>Row locks</td> * <td>Description</td> * </tr> * <tr> * <td>CONCUR_READ_ONLY</td> * <td>Read only</td> * <td>No</td> * <td>Read-only.</td> * </tr> * <tr> * <td>CONCUR_UPDATABLE</td> * <td>Optimistic concurrency, updatable</td> * <td>No</td> * <td>Row integrity checked with timestamp comparison or, when not available, value comparison (except text and image fields).</td> * </tr> * <tr> * <td>CONCUR_UPDATABLE+1</td> * <td>Pessimistic concurrency, updatable</td> * <td>Yes</td> * <td>Row integrity is ensured by locking rows.</td> * </tr> * <tr> * <td>CONCUR_UPDATABLE+2</td> * <td>Optimistic concurrency, updatable</td> * <td>No</td> * <td>Row integrity checked with value comparison (except text and image fields).</td> * </tr> * </table> * * @param type defined in <code>java.sql.ResultSet</code> * @param concurrency type defined in <code>java.sql.ResultSet</code> * @return <code>true</code> if so; <code>false</code> otherwise * @throws SQLException if a database access error occurs * * @see Connection * @see #supportsResultSetType */ public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { // jTDS supports both all standard ResultSet concurencies plus // CONCUR_UPDATABLE + 1 and CONCUR_UPDATABLE + 2, except the // TYPE_SCROLL_INSENSITIVE/CONCUR_UPDATABLE combination on SQL Server if (!supportsResultSetType(type)) { return false; } if (concurrency < ResultSet.CONCUR_READ_ONLY || concurrency > ResultSet.CONCUR_UPDATABLE + 2) { return false; } return type != ResultSet.TYPE_SCROLL_INSENSITIVE || concurrency == ResultSet.CONCUR_READ_ONLY; } /** * JDBC 2.0 Indicates whether a result set's own updates are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if updates are visible for the * result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean ownUpdatesAreVisible(int type) throws SQLException { return true; } /** * JDBC 2.0 Indicates whether a result set's own deletes are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if deletes are visible for the * result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean ownDeletesAreVisible(int type) throws SQLException { return true; } /** * JDBC 2.0 Indicates whether a result set's own inserts are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if inserts are visible for the * result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean ownInsertsAreVisible(int type) throws SQLException { return true; } /** * JDBC 2.0 Indicates whether updates made by others are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if updates made by others are * visible for the result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean othersUpdatesAreVisible(int type) throws SQLException { // Updates are visibile in scroll sensitive ResultSets return type >= ResultSet.TYPE_SCROLL_SENSITIVE; } /** * JDBC 2.0 Indicates whether deletes made by others are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if deletes made by others are * visible for the result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean othersDeletesAreVisible(int type) throws SQLException { // Deletes are visibile in scroll sensitive ResultSets return type >= ResultSet.TYPE_SCROLL_SENSITIVE; } /** * JDBC 2.0 Indicates whether inserts made by others are visible. * * @param type <code>ResultSet</code> type * @return <code>true</code> if inserts made by others are visible * for the result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean othersInsertsAreVisible(int type) throws SQLException { // Inserts are only visibile with dynamic cursors return type == ResultSet.TYPE_SCROLL_SENSITIVE + 1; } /** * JDBC 2.0 Indicates whether or not a visible row update can be detected * by calling the method <code>ResultSet.rowUpdated</code> . * * @param type <code>ResultSet</code> type * @return <code>true</code> if changes are detected by the * result set type; <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean updatesAreDetected(int type) throws SQLException { // Seems like there's no support for this in SQL Server return false; } /** * JDBC 2.0 Indicates whether or not a visible row delete can be detected * by calling ResultSet.rowDeleted(). If deletesAreDetected() returns * false, then deleted rows are removed from the result set. * * @param type <code>ResultSet</code> type * @return <code>true</code> if changes are detected by the result set type * @throws SQLException if a database access error occurs */ public boolean deletesAreDetected(int type) throws SQLException { return true; } /** * JDBC 2.0 Indicates whether or not a visible row insert can be detected * by calling ResultSet.rowInserted(). * * @param type <code>ResultSet</code> type * @return <code>true</code> if changes are detected by the result set type * @throws SQLException if a database access error occurs */ public boolean insertsAreDetected(int type) throws SQLException { // Seems like there's no support for this in SQL Server return false; } /** * JDBC 2.0 Indicates whether the driver supports batch updates. * * @return <code>true</code> if the driver supports batch updates; * <code>false</code> otherwise * @throws SQLException if a database access error occurs */ public boolean supportsBatchUpdates() throws SQLException { return true; } private void setCaseSensitiveFlag() throws SQLException { if (caseSensitive == null) { Statement s = connection.createStatement(); ResultSet rs = s.executeQuery("sp_server_info 16"); rs.next(); caseSensitive = "MIXED".equalsIgnoreCase(rs.getString(3)) ? Boolean.FALSE : Boolean.TRUE; s.close(); } } public java.sql.ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { String colNames[] = {"TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "ATTR_NAME", "DATA_TYPE", "ATTR_TYPE_NAME", "ATTR_SIZE", "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS", "ATTR_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH","ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATALOG", "SCOPE_SCHEMA", "SCOPE_TABLE", "SOURCE_DATA_TYPE"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.SMALLINT}; // // Return an empty result set // JtdsStatement dummyStmt = (JtdsStatement) connection.createStatement(); CachedResultSet rs = new CachedResultSet(dummyStmt, colNames, colTypes); rs.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rs; } /** * Returns the database major version. */ public int getDatabaseMajorVersion() throws SQLException { return connection.getDatabaseMajorVersion(); } /** * Returns the database minor version. */ public int getDatabaseMinorVersion() throws SQLException { return connection.getDatabaseMinorVersion(); } /** * Returns the JDBC major version. */ public int getJDBCMajorVersion() throws SQLException { return 3; } /** * Returns the JDBC minor version. */ public int getJDBCMinorVersion() throws SQLException { return 0; } public int getResultSetHoldability() throws SQLException { return JtdsResultSet.HOLD_CURSORS_OVER_COMMIT; } public int getSQLStateType() throws SQLException { return sqlStateXOpen; } public java.sql.ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { String colNames[] = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "SUPERTABLE_NAME"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR}; // // Return an empty result set // JtdsStatement dummyStmt = (JtdsStatement) connection.createStatement(); CachedResultSet rs = new CachedResultSet(dummyStmt, colNames, colTypes); rs.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rs; } public java.sql.ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { String colNames[] = {"TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SUPERTYPE_CAT", "SUPERTYPE_SCHEM", "SUPERTYPE_NAME"}; int colTypes[] = {Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR}; // // Return an empty result set // JtdsStatement dummyStmt = (JtdsStatement) connection.createStatement(); CachedResultSet rs = new CachedResultSet(dummyStmt, colNames, colTypes); rs.setConcurrency(ResultSet.CONCUR_READ_ONLY); return rs; } /** * Returns <code>true</code> if updates are made to a copy of the LOB; returns * <code>false</code> if LOB updates are made directly to the database. * <p> * NOTE: Since SQL Server / Sybase do not support LOB locators as Oracle does (AFAIK); * this method always returns <code>true</code>. */ public boolean locatorsUpdateCopy() throws SQLException { return true; } /** * Returns <code>true</code> if getting auto-generated keys is supported after a * statment is executed; returns <code>false</code> otherwise */ public boolean supportsGetGeneratedKeys() throws SQLException { return true; } /** * Returns <code>true</code> if Callable statements can return multiple result sets; * returns <code>false</code> if they can only return one result set. */ public boolean supportsMultipleOpenResults() throws SQLException { return true; } /** * Returns <code>true</code> if the database supports named parameters; * returns <code>false</code> if the database does not support named parameters. */ public boolean supportsNamedParameters() throws SQLException { return true; } public boolean supportsResultSetHoldability(int param) throws SQLException { // Not really sure about this one! return false; } /** * Returns <code>true</code> if savepoints are supported; returns * <code>false</code> otherwise */ public boolean supportsSavepoints() throws SQLException { return true; } /** * Returns <code>true</code> if the database supports statement pooling; * returns <code>false</code> otherwise. */ public boolean supportsStatementPooling() throws SQLException { return true; } /** * Format the supplied search pattern to transform the escape \x into [x]. * * @param pattern the pattern to tranform * @return the transformed pattern as a <code>String</code> */ private static String processEscapes(String pattern) { final char escChar = '\\'; if (pattern == null || pattern.indexOf(escChar) == -1) { return pattern; } int len = pattern.length(); StringBuilder buf = new StringBuilder(len + 10); for (int i = 0; i < len; i++) { if (pattern.charAt(i) != escChar) { buf.append(pattern.charAt(i)); } else if (i < len - 1) { buf.append('['); buf.append(pattern.charAt(++i)); buf.append(']'); } else { // Ignore final \ } } return buf.toString(); } /** * Format the supplied procedure call as a valid JDBC call escape. * * @param catalog the database name or null * @param call the stored procedure call to format * @return the formatted call escape as a <code>String</code> */ private String syscall(String catalog, String call) { StringBuilder sql = new StringBuilder(30 + call.length()); sql.append("{call "); if (catalog != null) { if (tdsVersion >= Driver.TDS70) { sql.append('[').append(catalog).append(']'); } else { sql.append(catalog); } sql.append(".."); } sql.append(call).append('}'); return sql.toString(); } /** * Uppercase all column names. * <p> * Sybase returns column names in lowecase while the JDBC standard suggests * they should be uppercase. * * @param results the result set to modify * @throws SQLException */ private static void upperCaseColumnNames(JtdsResultSet results) throws SQLException { ResultSetMetaData rsmd = results.getMetaData(); int cnt = rsmd.getColumnCount(); for (int i = 1; i <= cnt; i++) { String name = rsmd.getColumnLabel(i); if (name != null && name.length() > 0) { results.setColLabel(i, name.toUpperCase()); } } } private static CachedResultSet createTypeInfoResultSet(JtdsResultSet rs, boolean useLOBs) throws SQLException { CachedResultSet result = new CachedResultSet(rs, false); if (result.getMetaData().getColumnCount() > TypeInfo.NUM_COLS) { result.setColumnCount(TypeInfo.NUM_COLS); } result.setColLabel(3, "PRECISION"); result.setColLabel(11, "FIXED_PREC_SCALE"); upperCaseColumnNames(result); result.setConcurrency(ResultSet.CONCUR_UPDATABLE); result.moveToInsertRow(); for (Iterator iter = getSortedTypes(rs, useLOBs).iterator(); iter.hasNext();) { TypeInfo ti = (TypeInfo) iter.next(); ti.update(result); result.insertRow(); } result.moveToCurrentRow(); result.setConcurrency(ResultSet.CONCUR_READ_ONLY); return result; } private static Collection getSortedTypes(ResultSet rs, boolean useLOBs) throws SQLException { List types = new ArrayList(40); // 40 should be enough capacity to hold all types while (rs.next()) { types.add(new TypeInfo(rs, useLOBs)); } Collections.sort(types); return types; } /////// JDBC4 demarcation, do NOT put any JDBC3 code below this line /////// /* (non-Javadoc) * @see java.sql.DatabaseMetaData#autoCommitFailureClosesAllResultSets() */ public boolean autoCommitFailureClosesAllResultSets() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#getClientInfoProperties() */ public ResultSet getClientInfoProperties() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#getFunctionColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#getFunctions(java.lang.String, java.lang.String, java.lang.String) */ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#getRowIdLifetime() */ public RowIdLifetime getRowIdLifetime() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#getSchemas(java.lang.String, java.lang.String) */ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.DatabaseMetaData#supportsStoredFunctionsUsingCallSyntax() */ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ public boolean isWrapperFor(Class arg0) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Wrapper#unwrap(java.lang.Class) */ public Object unwrap(Class arg0) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } //// JDBC4.1 demarcation, do NOT put any JDBC3/4.0 code below this line //// @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } }
⏎ net/sourceforge/jtds/jdbc/JtdsDatabaseMetaData.java
Or download all of them as a single archive file:
File name: jtds-1.3.1-fyi.zip File size: 323160 bytes Release date: 2013-06-08 Download
⇐ What Is jtds-1.3.1-dist.zip?
2016-11-26, 7815👍, 0💬
Popular Posts:
Apache Commons Lang 3 is the 3rd version of Apache Commons Lang, which provides a host of helper uti...
What Is jsse.jar (JDK 6) Java Secure Socket Extension? jsse.jar, Java Secure Socket Extension, is Ja...
JDK 11 jdk.internal.vm.ci.jmod is the JMOD file for JDK 11 Internal VM CI module. JDK 11 Internal VM...
What Is log4j-1.2.15.jar? I got the JAR file from apache-log4j-1.2.15.zip. log4j-1.2.15.jar is the v...
Old version of xml-apis.jar. JAR File Size and Download Location: File name: xmlParserAPIs.jar File ...