All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.access.AS400JDBCDatabaseMetaData Maven / Gradle / Ivy

There is a newer version: 11.1
Show newest version
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: AS400JDBCDatabaseMetaData.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2010 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
/* ifdef JDBC40
import java.sql.RowIdLifetime;
endif */
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Vector;                            // @D0A





// @E4C
/**
The AS400JDBCDatabaseMetaData class provides information
about the database as a whole.

Some of the methods in this class take arguments that are pattern strings. Such arguments are suffixed with "Pattern". Within a pattern string, "%" means match any substring of zero or more characters, and "_" means match exactly one character. Only entries matching the pattern string are returned.

For example, if the schemaPattern argument for getTables() is "H%WO_LD", then the following schemas might match the pattern, provided they exist on the system:

HELLOWORLD
HIWORLD
HWORLD
HELLOWOULD
HIWOULD

In a pattern string, if you want to match the "_" or "%" characters exactly, then you need to escape the character by using the "\" character before it. For example, if the schemaPattern argument for getTables() is "SCHEM\_1", then only the schema SCHEM_1 will match the pattern.

Many of the methods here return lists of information in result sets. You can use the normal ResultSet methods to retrieve data from these result sets. The format of the result sets are described in the JDBC interface specification.

Schema and table names that are passed as input to methods in this class are implicitly uppercased unless enclosed in double-quotes. **/ //----------------------------------------------------------- // Using nulls and empty strings for catalog functions // // When the parameter is NOT search pattern capable and: // null is specified for: // catalog (system) - parameter is ignored // schema (library) - use default SQL schema // The default SQL schema can be // set in the URL. If not // specified in URL, the first // library specified in the library // properties is used as the // default SQL schema. // If no default SQL schema exists, // QGPL is used. // table (file) - empty result set is returned // column (field) - empty result set is returned // empty string is specified for: // catalog (system) - empty result set is returned // schema (library) - empty result set is returned // table (file) - empty result set is returned // column (field) - empty result set is returned // // // When the parameter is search pattern capable and: // null is specified for: // schemaPattern (library) - no value sent to system. // System default of // *USRLIBL is used. // tablePattern (file) - no value sent to system // system default of *ALL used // empty string is specified for: // schemaPattern (library) - empty result set is returned // tablePattern (file) - empty result set is returned // // //---------------------------------------------------------- public class AS400JDBCDatabaseMetaData /* ifdef JDBC40 extends ToolboxWrapper endif */ implements DatabaseMetaData { static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others."; //New constants for JDBC 3.0. public static final int sqlStateXOpen = 1; public static final int sqlStateSQL99 = 2; // Private data. AS400JDBCConnection connection_; private int id_; private SQLConversionSettings settings_; private boolean useDRDAversion_; //@mdsp misc constants for sysibm stored procedures final static int SQL_NO_NULLS = 0; //@mdsp final static int SQL_NULLABLE = 1; //@mdsp final static int SQL_NULLABLE_UNKNOWN = 2; //@mdsp final static int SQL_BEST_ROWID = 1; //@mdsp final static int SQL_ROWVER = 2; //@mdsp static final String EMPTY_STRING = ""; //@mdsp static final String MATCH_ALL = "%"; //@mdsp private static final String VIEW = "VIEW"; //@mdsp private static final String TABLE = "TABLE"; //@mdsp private static final String SYSTEM_TABLE = "SYSTEM TABLE"; //@mdsp private static final String ALIAS = "ALIAS"; //@mdsp private static final String MQT = "MATERIALIZED QUERY TABLE"; //@mdsp private static final String SYNONYM = "SYNONYM"; //@mdsp private static final String FAKE_VALUE = "QCUJOFAKE"; //@mdsp private static final int SQL_ALL_TYPES = 0; //@mdsp // the DB2 SQL reference says this should be 2147483647 but we return 1 less to allow for NOT NULL columns static final int MAX_LOB_LENGTH = 2147483646; //@xml3 static int javaVersion = 0; static { String javaVersionString = System.getProperty("java.version"); if (javaVersionString != null) { int dotIndex = javaVersionString.indexOf('.'); if (dotIndex > 0) { int secondDotIndex = javaVersionString.indexOf('.', dotIndex+1); if (secondDotIndex > 0) { String firstDigit = javaVersionString.substring(0,dotIndex); String secondDigit = javaVersionString.substring(dotIndex+1, secondDotIndex); javaVersion = Integer.parseInt(firstDigit)*10 + Integer.parseInt(secondDigit); } } else { // Android return 0. Set as version 4. @G3A if ("0".equals(javaVersionString)) { javaVersion = 4; } // Java 9 returns 9 or 9-internal if (javaVersionString.charAt(0) == '9') { javaVersion = 19; } } } } /** Constructs an AS400JDBCDatabaseMetaData object. @param connection The connection to the system. @param id The ID the caller has assigned to this AS400JDBCDatabaseMetaData. **/ AS400JDBCDatabaseMetaData (AS400JDBCConnection connection, int id, boolean useDRDAversion) throws SQLException { connection_ = connection; settings_ = SQLConversionSettings.getConversionSettings(connection); id_ = id; useDRDAversion_ = useDRDAversion; } /** Indicates if all of the procedures returned by getProcedures() can be called by the current user. @return Always false. This driver cannot determine if all of the procedures can be called by the current user. @exception SQLException This exception is never thrown. **/ public boolean allProceduresAreCallable () throws SQLException { return false; } /** Indicates if all of the tables returned by getTables() can be SELECTed by the current user. @return Always false. This driver cannot determine if all of the tables returned by getTables() can be selected by the current user. @exception SQLException This exception is never thrown. **/ public boolean allTablesAreSelectable () throws SQLException { return false; } /** Indicates if a data definition statement within a transaction can force the transaction to commit. @return Always false. A data definition statement within a transaction does not force the transaction to commit. @exception SQLException This exception is never thrown. **/ public boolean dataDefinitionCausesTransactionCommit () throws SQLException { return false; } /** Indicates if a data definition statement within a transaction is ignored. @return Always false. A data definition statement within a transaction is not ignored. @exception SQLException This exception is never thrown. **/ public boolean dataDefinitionIgnoredInTransactions () throws SQLException { return false; } // JDBC 2.0 /** Indicates if visible deletes to a result set of the specified type can be detected by calling ResultSet.rowDeleted(). If visible deletes cannot be detected, then rows are removed from the result set as they are deleted. @param resultSetType The result set type. Value values are:

  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return Always false. Deletes can not be detected by calling ResultSet.rowDeleted(). @exception SQLException If the result set type is not valid. **/ public boolean deletesAreDetected (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return false; } /** Indicates if getMaxRowSize() includes blobs when computing the maximum length of a single row. @return Always true. getMaxRowSize() does include blobs when computing the maximum length of a single row. @exception SQLException This exception is never thrown. **/ public boolean doesMaxRowSizeIncludeBlobs () throws SQLException { return true; } //@G4A /** Returns a ResultSet containing a description of type attributes available in a specified catalog. This method only applies to the attributes of a structured type. Distinct types are stored in the datatypes catalog, not the attributes catalog. Since DB2 for IBM i does not support structured types at this time, an empty ResultSet will always be returned for calls to this method. @param catalog The catalog name. @param schemaPattern The schema name pattern. @param typeNamePattern The type name pattern. @param attributeNamePattern The attribute name pattern. @return The empty ResultSet @exception SQLException This exception is never thrown. @since Modification 5 **/ public ResultSet getAttributes (String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { // We return an empty result set because this is not supported by our driver Statement statement = connection_.createStatement(); // TODO: Add this to all methods if (statement instanceof AS400JDBCStatement) { AS400JDBCStatement stmt= (AS400JDBCStatement) statement; stmt.closeOnCompletion(); } ResultSet rs = statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " + "VARCHAR('2', 128) AS TYPE_SCHEM, " + "VARCHAR('3', 128) AS TYPE_NAME, " + "VARCHAR('4', 128) AS ATTR_NAME, " + "SMALLINT(5) AS DATA_TYPE, " + "VARCHAR('6', 128) AS ATTR_TYPE_NAME, " + "INT(7) AS ATTR_SIZE, " + "INT(8) AS DECIMAL_DIGITS, " + "INT(9) AS NUM_PREC_RADIX, " + "INT(10) AS NULLABLE, " + "VARCHAR('11', 128) AS REMARKS, " + "VARCHAR('12', 128) AS ATTR_DEF, " + "INT(13) AS SQL_DATA_TYPE, " + "INT(14) AS SQL_DATETIME_SUB, " + "INT(15) AS CHAR_OCTET_LENGTH, " + "INT(16) AS ORDINAL_POSITION, " + "VARCHAR('17', 128) AS IS_NULLABLE, " + "VARCHAR('18', 128) AS SCOPE_CATALOG, " + "VARCHAR('19', 128) AS SCOPE_SCHEMA, " + "VARCHAR('20', 128) AS SCOPE_TABLE, " + "SMALLINT(21) AS SOURCE_DATA_TYPE " + "FROM QSYS2" + getCatalogSeparator() + "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY "); return rs; } /** Returns a description of a table's optimal set of columns that uniquely identifies a row. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified and a default SQL schema was not specified in the URL and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @param scope The scope of interest. Valid values are: bestRowTemporary and bestRowTransaction. bestRowSession is not allowed because it cannot be guaranteed that the row will remain valid for the session. If bestRowSession is specified, an empty result set is returned. If bestRowTransaction is specified, autocommit is false, and transaction is set to repeatable read, then results is returned; otherwise, an empty result set is returned. @param nullable The value indicating if columns that are nullable should be included. @return The ResultSet containing a table's optimal set of columns that uniquely identify a row. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getBestRowIdentifier (String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 DBReplyRequestedDS getBestRowIdentifierReply = null; //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator () + "SQLSPECIALCOLUMNS(?,?,?,?,?,?,?)"); cstmt.setShort(1, (short)SQL_BEST_ROWID); cstmt.setString(2, normalize(catalog)); cstmt.setString(3, normalize(schema)); cstmt.setString(4, normalize(table)); cstmt.setShort(5, (short) scope); if (nullable) { cstmt.setShort(6, (short) SQL_NULLABLE); } else { cstmt.setShort(6, (short) SQL_NO_NULLS); } cstmt.setString(7, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cstmt.execute(); ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } // Initialize the format of the result set. String[] fieldNames = { "SCOPE", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "PSEUDO_COLUMN", }; SQLData[] sqlData = { new SQLSmallint (vrm, settings_), // scope //@trunc3 new SQLVarchar (128, settings_), // column name new SQLSmallint (vrm, settings_), // data type //@trunc3 new SQLVarchar (128, settings_), // type name new SQLInteger (vrm, settings_), // column size //@trunc3 new SQLInteger (vrm, settings_), // buffer length //@trunc3 new SQLSmallint (vrm, settings_), // decimal digits //@trunc3 new SQLSmallint (vrm, settings_), // pseudo column //@trunc3 }; int[] fieldNullables = { columnNoNulls, // scope columnNoNulls, // column name columnNoNulls, // data type columnNoNulls, // type name columnNoNulls, // column size columnNoNulls, // buffer length columnNoNulls, // decimal digits columnNoNulls, // pseudo column }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if (!isCatalogValid(catalog) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // Table is null (table==null) || // Table is empty string (table.length()==0 ) || // Scope. // If bestRowSession is specified, return empty set // since it can not be guaranteed that the row will // remain valid for the session. // If bestRowTemporary is specified, return results. // If bestRowTransaction is specified and autocommit // is true or transaction is not repeatableRead, return // empty result set ((scope == bestRowSession) || ( (scope == bestRowTransaction) && ( (connection_.getAutoCommit()==true) || (connection_.getTransactionIsolation() != Connection.TRANSACTION_REPEATABLE_READ))))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_SPECIAL_COLUMN_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the library name if (schema == null) { // use default SQL schema or qgpl request.setLibraryName(connection_.getDefaultSchema(), connection_.getConverter()); //@P0C } else request.setLibraryName(normalize(schema), connection_.getConverter()); // @E4C @P0C // Set the table name request.setFileName(normalize(table), connection_.getConverter()); // @E4C @P0C // Set the Field Information to Return Bitmap // Return library, table, and column request.setSpecialColumnsReturnInfoBitmap(0x1F000000); // Set the short / long file and field name indicator request.setFileShortOrLongNameIndicator(0xF0); // Long // Set if columns are nullable request.setSpecialColumnsNullableIndicator(nullable ? 0xF1 : 0xF0); //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- // Dead code // if (getBestRowIdentifierReply != null) { // getBestRowIdentifierReply.returnToPool(); // getBestRowIdentifierReply=null; //} getBestRowIdentifierReply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = getBestRowIdentifierReply.getErrorClass(); if (errorClass !=0) { int returnCode = getBestRowIdentifierReply.getReturnCode(); JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = getBestRowIdentifierReply.getDataFormat(); DBData resultData = getBestRowIdentifierReply.getResultData(); if (resultData != null) { JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); JDFieldMap[] maps = new JDFieldMap[8]; maps[0] = new JDHardcodedFieldMap(new Short ((short) scope)); // scope maps[1] = new JDSimpleFieldMap (1); // column name maps[2] = new JDDataTypeFieldMap (2, 4, 3, 5, 0, connection_.getVRM(), connection_.getProperties()); // @M0C // data type - converted to short //@KKB pass 0 for ccsid since cannot get ccsid from host server maps[3] = new JDSimpleFieldMap (2); // type name maps[4] = new JDSimpleFieldMap (4); // column size (length) maps[5] = new JDHardcodedFieldMap(new Integer (0)); // buffer length maps[6] = new JDSimpleFieldMap (5); // decimal digits (scale) maps[7] = new JDHardcodedFieldMap(new Short ((short) versionColumnNotPseudo)); JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // Cannot return to pool yet because array in use by resultData. Pased to result set to be closed there // if (getBestRowIdentifierReply != null) getBestRowIdentifierReply.returnToPool(); } } } catch (DBDataStreamException e) { JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "BestRowIdentifier", connection_, getBestRowIdentifierReply); //@in2 } /** Returns the catalog name available in this database. This will return a ResultSet with a single row, whose value is the IBM i system name. @return The ResultSet containing the IBM i system name. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getCatalogs () throws SQLException { connection_.checkOpen (); //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLTABLES(?,?,?,?,?)"); cstmt.setString(1, "%"); cstmt.setString(2, "%"); cstmt.setString(3, "%"); cstmt.setString(4, "%"); cstmt.setString(5, "DATATYPE='JDBC';GETCATALOGS=1;CURSORHOLD=1"); cstmt.execute(); ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } String[] fieldNames = {"TABLE_CAT"}; SQLData[] sqlData = { new SQLVarchar (128, settings_)}; int[] fieldNullables = {columnNoNulls}; // Catalog Name JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); Object[][] data = { { connection_.getCatalog()}}; boolean[][] nulls = {{false}}; boolean[][] dataMappingErrors = {{false}}; // If running to a system running OS/400 v5r2 or IBM i the list can contain more than just the system // name (when IASPs are on the system). Try to retrieve that list. Note // if getting the list fails we will still return a result set containing // one item -- the name of the system. We just built that result set // (the previous six lines of code) and that is what we will return. That // result set will be consistent with the result set returned when connecting // to OS/400 v5r1 or earlier versions. If getting the list works we will // build and return a new result set containing data retrieved from the system. if (connection_.getVRM() >= JDUtilities.vrm520) // @F1a { // @F1a try { // @F1a // @F1a Vector RDBEntries = new Vector(); // @F1a Statement statement = null; //@scan1 ResultSet rs = null; //@scan1 try { statement = connection_.createStatement(); // @F1a rs = statement.executeQuery("SELECT LOCATION FROM QSYS2" + getCatalogSeparator() + "SYSCATALOGS WHERE RDBTYPE = 'LOCAL' AND RDBASPSTAT='AVAILABLE' "); // @F1a while (rs.next()) // @F1a { // @F1a RDBEntries.add(rs.getString(1).trim()); // @F1a } }finally //@scan1 { try{ if(rs != null) rs.close(); }catch(Exception e){ JDTrace.logException(this, "getCatalogs rs.close()", e); } //allow next close to execute if(statement != null) statement.close(); } int count = RDBEntries.size(); // @F1a if (count > 0) // @F1a { // @F1a data = new Object[count][1]; // @F1a nulls = new boolean[count][1]; // @F1a dataMappingErrors = new boolean[count][1]; for (int i=0; i 16) { cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.1';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4 } else { cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4 } endif */ /* ifndef JDBC40 */ cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); /* endif */ try { cs.execute(); // Catch a resource limit error for applications that are not // closing result sets. } catch (SQLException e) { if (e.getErrorCode() == -7049) { // Cleanup by running the GC and waiting System.gc(); try { Thread.sleep(1000); } catch (InterruptedException e1) { } // Retry cs.execute(); } else { throw e; } } ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs // Create an return the result set for the request. // Note: This will failed until SQLCOLUMNS returns more columns // return new DB2RSGetColumns40(x, isTransactional); } if (!isJDBC3) //@F2A { // Set up the result set in the format required by JDBC fieldNames = new String[] {"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", }; sqlData = new SQLData[] { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // library new SQLVarchar (128, settings_), // table new SQLVarchar (128, settings_), // column new SQLSmallint (vrm, settings_), // data type //@trunc3 new SQLVarchar (128, settings_), // type name new SQLInteger (vrm, settings_), // column size //@trunc3 new SQLInteger (vrm, settings_), // buffer length //@trunc3 new SQLInteger (vrm, settings_), // decimal digits //@trunc3 new SQLInteger (vrm, settings_), // radix //@trunc3 new SQLInteger (vrm, settings_), // nullable //@trunc3 new SQLVarchar (254, settings_), // remarks new SQLVarchar ((connection_.getVRM() >= JDUtilities.vrm610) ? 2000 : 254, settings_), // column def //@550 Column default value support new SQLInteger (vrm, settings_), // sql data type //@trunc3 new SQLInteger (vrm, settings_), // datetime sub //@trunc3 new SQLInteger (vrm, settings_), // octet length //@trunc3 new SQLInteger (vrm, settings_), // ordinal //@trunc3 new SQLVarchar (254, settings_), // is nullable }; fieldNullables = new int[] {columnNullable, // catalog columnNullable, // library columnNoNulls, // table columnNoNulls, // column columnNoNulls, // data type columnNoNulls, // type name columnNoNulls, // column size columnNoNulls, // buffer length columnNoNulls, // decimal digits columnNoNulls, // radix columnNoNulls, // nullable columnNullable, // remarks columnNullable, // column def columnNoNulls, // sql data type columnNoNulls, // datetime sub columnNoNulls, // octet length columnNoNulls, // ordinal columnNoNulls, // is nullable }; } else { //@F2A // Set up the result set in the format required by JDBC fieldNames = new String[] {"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", /* ifdef JDBC40 "SCOPE_CATLOG", //@G4A endif */ /* ifndef JDBC40 */ "SCOPE_CATALOG", //@G4A /* endif */ "SCOPE_SCHEMA", //@G4A "SCOPE_TABLE", //@G4A /* ifndef JDBC40 */ "SOURCE_DATA_TYPE" //@G4A /* endif */ /* ifdef JDBC40 "SOURCE_DATA_TYPE", //@G4A "IS_AUTOINCREMENT" //jdbc40 endif */ }; sqlData = new SQLData[] { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // library new SQLVarchar (128, settings_), // table new SQLVarchar (128, settings_), // column new SQLSmallint (vrm, settings_), // data type //@trunc3 new SQLVarchar (128, settings_), // type name new SQLInteger (vrm, settings_), // column size //@trunc3 new SQLInteger (vrm, settings_), // buffer length //@trunc3 new SQLInteger (vrm, settings_), // decimal digits //@trunc3 new SQLInteger (vrm, settings_), // radix //@trunc3 new SQLInteger (vrm, settings_), // nullable //@trunc3 new SQLVarchar (254, settings_), // remarks new SQLVarchar ((connection_.getVRM() >= JDUtilities.vrm610) ? 2000 : 254, settings_), // column def new SQLInteger (vrm, settings_), // sql data type //@trunc3 new SQLInteger (vrm, settings_), // datetime sub //@trunc3 new SQLInteger (vrm, settings_), // octet length //@trunc3 new SQLInteger (vrm, settings_), // ordinal //@trunc3 new SQLVarchar (254, settings_), // is nullable new SQLVarchar (128, settings_), // scope catalog //@G4A new SQLVarchar (128, settings_), // scope schema //@G4A new SQLVarchar (128, settings_), // scope table //@G4A new SQLSmallint (vrm, settings_), // source data type //@G4A //@trunc3 /* ifdef JDBC40 new SQLVarchar (128, settings_), // is autoincrement //jdbc40 endif */ }; fieldNullables = new int[] {columnNullable, // catalog columnNullable, // library columnNoNulls, // table columnNoNulls, // column columnNoNulls, // data type columnNoNulls, // type name columnNoNulls, // column size columnNoNulls, // buffer length columnNoNulls, // decimal digits columnNoNulls, // radix columnNoNulls, // nullable columnNullable, // remarks columnNullable, // column def columnNoNulls, // sql data type columnNoNulls, // datetime sub columnNoNulls, // octet length columnNoNulls, // ordinal columnNoNulls, // is nullable columnNullable, // scope catalog //@G4A columnNullable, // scope schema //@G4A columnNullable, // scope table //@G4A columnNullable, // source data type //@G4A /* ifdef JDBC40 columnNoNulls, // is autoincrement //jdbc40 endif */ }; } JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows that // are readable one at a time try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if (!isCatalogValid(catalog) || // catalog is empty string // schema is not null and is empty string ((schemaPattern != null) && (schemaPattern.length()==0)) || // table is not null and is empty string ((tablePattern != null) && (tablePattern.length()==0)) || // columnPattern is not null and is empty string ((columnPattern != null) && (columnPattern.length()==0))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } //-------------------------------------------------- // Set the parameters for the request //-------------------------------------------------- else { // parameter values are valid, continue to build request // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FIELD_INFO, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the Library Name and Library Name Search Pattern parameters // If null, do not set parameter. The system default value of // *USRLIBL is used if (schemaPattern != null) { JDSearchPattern schema = new JDSearchPattern(schemaPattern); request.setLibraryName (normalize(schema.getPatternString()), connection_.getConverter()); // @E4C @P0C request.setLibraryNameSearchPatternIndicator(schema.getIndicator()); } // Set the Table Name and Table Name Search Pattern parameters // If null, do not set parameter. The system default value of // *ALL is used. if (tablePattern!=null) { JDSearchPattern table = new JDSearchPattern(tablePattern); request.setFileName (normalize(table.getPatternString()), connection_.getConverter()); // @E4C @P0C request.setFileNameSearchPatternIndicator(table.getIndicator()); } // Set the Field Name and Field Name Search Pattern parameters // If null, do not set parameter. The system default value of // *ALL is used. if (columnPattern!=null) { JDSearchPattern field = new JDSearchPattern(columnPattern); request.setFieldName (field.getPatternString(), connection_.getConverter()); //@P0C request.setFieldNameSearchPatternIndicator(field.getIndicator()); } // Set the short / long file and field name indicator request.setFileShortOrLongNameIndicator(0xF0); // Long // Set the Field Information to Return Bitmap // Return everything but the reserved fields if(connection_.getVRM() >= JDUtilities.vrm610) //@550 column default value support request.setFieldReturnInfoBitmap(0xEFF70000); //@550 request column default, 16th bit else //@550 request.setFieldReturnInfoBitmap(0xEFF60000); // @E3C //@KKB changed from EFF20000 inorder to request CCSID // Set the Field Information Order By Indicator parameter // Order by: Schema and File and Ordinal Position. request.setFieldInformationOrderByIndicator (2); // @E5C //------------------------------------------------------- // Send the request and cache all results from the system //------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); // Put the data format into a row format object JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); // Put the result data into a row cache JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. JDFieldMap[] maps = null; //@F2C if (!isJDBC3) //@F2A maps = new JDFieldMap[18]; else /* ifdef JDBC40 maps = new JDFieldMap[23]; //@G4A //jdbc40 endif */ /* ifndef JDBC40 */ maps = new JDFieldMap[22]; //@G4A /* endif */ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleFieldMap (1); // library maps[2] = new JDSimpleFieldMap (3); // table maps[3] = new JDSimpleFieldMap (4); // column maps[4] = new JDDataTypeFieldMap (6, 7, 10, 11, 12, connection_.getVRM(), connection_.getProperties()); // @M0C // Data type //@KKB include ccsid maps[5] = new JDLocalNameFieldMap (6, 7, 10, 11, 12, connection_.getVRM(), connection_.getProperties()); // @M0C // Type name //@KKB include ccsid maps[6] = new JDPrecisionFieldMap (6, 7, 10, 11, 12, connection_.getVRM(), connection_.getProperties()); // @M0C // column size (length) //@KKB include ccsid maps[7] = new JDHardcodedFieldMap(new Integer(0)); // Buffer - not used maps[8] = new JDScaleFieldMap (6, 7, 10, 11, 12, connection_.getVRM(), connection_.getProperties()); // @M0C // decimal digits (scale) //@KKB include ccsid maps[9] = new JDSimpleFieldMap (9); // radix maps[10] = new JDNullableIntegerFieldMap(8); // is null capable? if (connection_.getProperties().equals (JDProperties.REMARKS, JDProperties.REMARKS_SQL)) maps[11] = new JDSimpleFieldMap (2); // return remarks else maps[11] = new JDSimpleFieldMap (5); // return text // Always return null if V5R4 or earlier if(connection_.getVRM() <= JDUtilities.vrm540) //@550 column default value support maps[12] = new JDHardcodedFieldMap (new SQLVarchar(0, settings_), true, false); // column def else //@550 return what we are returned maps[12] = new JDSimpleFieldMap(14); // Per JDBC api - not used - hardcode to 0 maps[13] = new JDHardcodedFieldMap (new Integer (0)); // SQL data type // Per JDBC api - not used - hardcode to 0 maps[14] = new JDHardcodedFieldMap (new Integer (0)); // SQL datetime maps[15] = new JDCharOctetLengthFieldMap(6, 7, 10, 11, 12, connection_.getVRM(), connection_.getProperties()); // octet // @M0C //@KKB include ccsid // If the server functional level is 7 or greater, then ordinal @E3A // position is supported. Otherwise, just hardcode to -1. @E3A if (connection_.getServerFunctionalLevel() >= 7) // @E3A maps[16] = new JDSimpleFieldMap(13); // @E3A //@KKB changed from 12 since requesting ccsid else // @E3A maps[16] = new JDHardcodedFieldMap(new Integer(-1)); maps[17] = new JDNullableStringFieldMap(8); // is Nullable //@G4A The below fields will all return null. They are not supported //@G4A by our database. if (isJDBC3) //@F2A { maps[18] = new JDHardcodedFieldMap ("", true, false); // scope catalog //@G4A maps[19] = new JDHardcodedFieldMap ("", true, false); // scope schema //@G4A maps[20] = new JDHardcodedFieldMap ("", true, false); // scope table //@G4A maps[21] = new JDHardcodedFieldMap (new Short((short) 0)); // source data type //@G4A /* ifdef JDBC40 maps[22] = new JDHardcodedFieldMap (""); // is autoincrement "" till switch to sysibm //jdbc40 endif */ } // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // end of else blank } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Columns", connection_, reply); //@in2 } // End of getColumns // JDBC 2.0 /** Returns the connection for this metadata. @return The connection for this metadata. @exception SQLException This exception is never thrown. **/ public Connection getConnection () throws SQLException { return connection_; } /** Returns a description of the foreign key columns in the foreign key table that references the primary key columns of the primary key table. This is a description of how the primary table imports the foreign table's key. @param primaryCatalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param primarySchema The name of the schema where the primary table is located. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified,a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set is returned. @param primaryTable The primary table name. If null or empty string is specified, an empty result set is returned. @param foreignCatalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param foreignSchema The name of the schema where the primary table is located. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set is returned. @param foreignTable The foreign table name. If null or empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the foreign key columns in the foreign key table that references the primary key columns of the primary key table. @exception SQLException If the connection is not open or an error occurs. **/ //-------------------------------------------------// // The system returns the following: // 0 = cascade // 1 = No action or restrict // 2 = set null or set default // // JDBC has 5 possible values: // importedKeyNoAction // importedKeyCascade // importedKeySetNull // importedKeySetDefault // importedKeyRestrict // // Since the system groups together // some of the values, all of the // possible JDBC values can not be returned. // // For Update Rule, the only values // supported by the system are // no action and restrict. Since // the value of 1 is returned for // both no action and restrict, // the value of importKeyRestrict // will always be returned for the // update rule. // // For Delete Rule // the following is returned. It is // consistent with the ODBC implementation. // if 0 from system = importedKeyCascade // if 1 from system = importedKeyRestrict // if 2 from system = importedKeySetNull // // // importedKeyNoAction and importedKeySetDefault // will not be returned. //-------------------------------------------------// public ResultSet getCrossReference (String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall( JDSQLStatement.METADATA_CALL+ getCatalogSeparator() +"SQLFOREIGNKEYS(?,?,?,?,?,?,?)"); cs.setString(1, normalize(primaryCatalog)); cs.setString(2, normalize(primarySchema)); cs.setString(3, normalize(primaryTable)); cs.setString(4, normalize(foreignCatalog)); cs.setString(5, normalize(foreignSchema)); cs.setString(6, normalize(foreignTable)); cs.setString(7, "DATATYPE='JDBC';EXPORTEDKEY=0;IMPORTEDKEY=0;DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"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", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // pk catalog new SQLVarchar (128, settings_), // pk schema new SQLVarchar (128, settings_), // pk table new SQLVarchar (128, settings_), // pk column new SQLVarchar (128, settings_), // fk catalog new SQLVarchar (128, settings_), // fk schema new SQLVarchar (128, settings_), // fk table new SQLVarchar (128, settings_), // fk column new SQLSmallint (vrm, settings_), // key seq //@trunc3 new SQLSmallint (vrm, settings_), // update rule //@trunc3 new SQLSmallint (vrm, settings_), // delete rule //@trunc3 new SQLVarchar (128, settings_), // fk name new SQLVarchar (128, settings_), // pk name new SQLSmallint (vrm, settings_), // deferrability //@trunc3 }; int[] fieldNullables = {columnNullable, // pk catalog columnNullable, // pk schema columnNoNulls, // pk table columnNoNulls, // pk column columnNullable, // fk catalog columnNullable, // fk schema columnNoNulls, // fk table columnNoNulls, // fk column columnNoNulls, // key seq columnNoNulls, // update rule columnNoNulls, // delete rule columnNullable, // fk name columnNullable, // pk name columnNoNulls, // deferrability }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(primaryCatalog)) || // primarycatalog is empty string (!isCatalogValid(foreignCatalog)) || // foreigncatalog is empty string // primarySchema is not null and is empty string ((primarySchema != null) && (primarySchema.length()==0)) || // foreignSchema is not null and is empty string ((foreignSchema != null) && (foreignSchema.length()==0)) || // primaryTable is null or empty string (primaryTable==null) || (primaryTable.length()==0 ) || // foreignTable is null or empty string (foreignTable==null) || (foreignTable.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FOREIGN_KEY_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the primary key file library name if (primarySchema == null) { // use default SQL schema or qgpl request.setPrimaryKeyFileLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C @P0C } else request.setPrimaryKeyFileLibraryName(normalize(primarySchema), connection_.getConverter()); // @E4C @P0C // Set the foreign key file library name if (foreignSchema == null) { // use default SQL schema or qgpl request.setForeignKeyFileLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C @P0C } else request.setForeignKeyFileLibraryName(normalize(foreignSchema), connection_.getConverter()); // @E4C @P0C // Set the primary key table name request.setPrimaryKeyFileName(normalize(primaryTable), connection_.getConverter()); // @E4C @P0C // Set the foreign key table name request.setForeignKeyFileName(normalize(foreignTable), connection_.getConverter()); // @E4C @P0C // Set the Foreign key Information to Return Bitmap request.setForeignKeyReturnInfoBitmap(0xBBE00000); //Get the long file name request.setFileShortOrLongNameIndicator (0xF0); // @PDA Long table names. //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); // reply cannot be null at this point reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { // Put the data format into a row format object JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); // Put the result data into a row cache JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. JDFieldMap[] maps = new JDFieldMap[14]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleFieldMap (1); // pk schema maps[2] = new JDSimpleFieldMap (2); // pk table maps[3] = new JDSimpleFieldMap (3); // pk column maps[4] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[5] = new JDSimpleFieldMap (4); // fk schema maps[6] = new JDSimpleFieldMap (5); // fk table maps[7] = new JDSimpleFieldMap (6); // fk column maps[8] = new JDSimpleFieldMap (7); // key seq maps[9] = new JDUpdateDeleteRuleFieldMap (8); // update rule maps[10] = new JDUpdateDeleteRuleFieldMap (9); // delete rule maps[11] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false); maps[12] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false); maps[13] = new JDHardcodedFieldMap(new Short ((short) importedKeyNotDeferrable)); // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "CrossReference", connection_, reply); //@in2 } // End of getCrossReference /** Returns the major version number of the database. @return The major version number. @since Modification 5 **/ public int getDatabaseMajorVersion () { //return 5; //@610 //@610 get this dynamically since we can now have version 5 or 6 int defaultVersion = 0; //since we do not want to change signature to throw exception, have default as 0 try { String v = getDatabaseProductVersion(); int dotIndex = v.indexOf('.'); if (dotIndex > 0) { v = v.substring(0,dotIndex); defaultVersion = Integer.parseInt(v); } }catch(Exception e) { //should not happen } return defaultVersion; } /** Returns the minor version number of the database. @return The minor version number. @since Modification 5 **/ public int getDatabaseMinorVersion () { //return 0; //@610 //@610 get this dynamically since we can now as Native driver does int defaultVersion = 0; try { String v = getDatabaseProductVersion(); int dotIndex = v.indexOf('.'); if (dotIndex > 0) { v = v.substring(dotIndex+1); dotIndex = v.indexOf('.'); if (dotIndex > 0) { v = v.substring(0,dotIndex); } defaultVersion = Integer.parseInt(v); } }catch(Exception e) { //should not happen } return defaultVersion; } /** Returns the name of this database product. @return The database product name. @exception SQLException This exception is never thrown. **/ public String getDatabaseProductName () throws SQLException { return AS400JDBCDriver.DATABASE_PRODUCT_NAME_; // @D2C } /** Returns the version of this database product. @return The product version. @exception SQLException If the connection is not open or an error occurs. **/ public String getDatabaseProductVersion () throws SQLException { if (useDRDAversion_) { return getDatabaseProductVersionDRDA(); } else { return getDatabaseProductVersionI(); } } public String getDatabaseProductVersionI () throws SQLException { // The ODBC specification suggests the // format "vv.rr.mmmm product-specific". // Although the JDBC specification does not // mention this format, I will adopt it anyway. // // The format of the product-specific part is // "VxRxmx". I am not sure why the "m" is lowercase, // but somebody somewhere said this is normal, and // its a nit anyway. connection_.checkOpen(); AS400ImplRemote as400_ = (AS400ImplRemote) connection_.getAS400 (); int v, r, m; try { int vrm = as400_.getVRM (); v = (vrm & 0xffff0000) >>> 16; // @D1C r = (vrm & 0x0000ff00) >>> 8; // @D1C m = (vrm & 0x000000ff); // @D1C } catch (Exception e) { JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE); return null; } StringBuffer buffer = new StringBuffer (); buffer.append (JDUtilities.padZeros (v, 2)); buffer.append ("."); buffer.append (JDUtilities.padZeros (r, 2)); buffer.append ("."); buffer.append (JDUtilities.padZeros (m, 4)); buffer.append (" V"); buffer.append (v); buffer.append ("R"); buffer.append (r); buffer.append ("m"); buffer.append (m); return buffer.toString (); } /** Returns the DRDA format version of this database product. @return The product version. @exception SQLException If the connection is not open or an error occurs. **/ public String getDatabaseProductVersionDRDA () throws SQLException { // The DRDA format is QSQvvrrm // for example QSQ07020 // connection_.checkOpen(); AS400ImplRemote as400_ = (AS400ImplRemote) connection_.getAS400 (); int v, r, m; int vrm = as400_.getVRM (); v = (vrm & 0xffff0000) >>> 16; // @D1C r = (vrm & 0x0000ff00) >>> 8; // @D1C m = (vrm & 0x000000ff); // @D1C StringBuffer buffer = new StringBuffer (); buffer.append("QSQ"); if (v < 10) buffer.append("0"); buffer.append(v); if (r < 10) buffer.append("0"); buffer.append(r); buffer.append(m); return buffer.toString (); } /** Returns the default transaction isolation level. @return The default transaction isolation level. @exception SQLException This exception is never thrown. **/ public int getDefaultTransactionIsolation () throws SQLException { String levelAsString = connection_.getProperties ().getString (JDProperties.TRANSACTION_ISOLATION); return JDTransactionManager.mapStringToLevel (levelAsString); } /** Returns the major version number for this JDBC driver. @return The major version number. **/ public int getDriverMajorVersion () { return AS400JDBCDriver.MAJOR_VERSION_; } /** Returns the minor version number for this JDBC driver. @return The minor version number. **/ public int getDriverMinorVersion () { return AS400JDBCDriver.MINOR_VERSION_; } /** Returns the name of this JDBC driver. @return The driver name. @exception SQLException This exception is never thrown. **/ public String getDriverName () throws SQLException { return AS400JDBCDriver.DRIVER_NAME_; // @D2C } /** Returns the version of this JDBC driver. @return The driver version. @exception SQLException This exception is never thrown. **/ public String getDriverVersion () throws SQLException { return AS400JDBCDriver.MAJOR_VERSION_+ "."+ AS400JDBCDriver.MINOR_VERSION_; } /** Returns a description of the foreign key columns that reference a table's primary key columns. This is the foreign keys exported by a table. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the foreign key columns that reference a table's primary key columns. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getExportedKeys (String catalog, String schema, String table) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLFOREIGNKEYS(?,?,?,?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schema)); cs.setString(3, normalize(table)); cs.setString(4, normalize(catalog)); cs.setString(5, EMPTY_STRING); cs.setString(6, EMPTY_STRING); cs.setString(7, "DATATYPE='JDBC';EXPORTEDKEY=1; CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"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", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // pk catalog new SQLVarchar (128, settings_), // pk schema new SQLVarchar (128, settings_), // pk table new SQLVarchar (128, settings_), // pk column new SQLVarchar (128, settings_), // fk catalog new SQLVarchar (128, settings_), // fk schema new SQLVarchar (128, settings_), // fk table new SQLVarchar (128, settings_), // fk column new SQLSmallint (vrm, settings_), // key seq //@trunc3 new SQLSmallint (vrm, settings_), // update rule //@trunc3 new SQLSmallint (vrm, settings_), // delete rule //@trunc3 new SQLVarchar (128, settings_), // fk name new SQLVarchar (128, settings_), // pk name new SQLSmallint (vrm, settings_), // deferrability //@trunc3 }; int[] fieldNullables = {columnNullable, // pk catalog columnNullable, // pk schema columnNoNulls, // pk table columnNoNulls, // pk column columnNullable, // fk catalog columnNullable, // fk schema columnNoNulls, // fk table columnNoNulls, // fk column columnNoNulls, // key seq columnNoNulls, // update rule columnNoNulls, // delete rule columnNullable, // fk name columnNullable, // pk name columnNoNulls, // deferrability }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // table is null or empty string (table==null) || (table.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FOREIGN_KEY_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the primary key file library name if (schema == null) { // use default SQL schema or qgpl request.setPrimaryKeyFileLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C @P0C } else request.setPrimaryKeyFileLibraryName(normalize(schema), connection_.getConverter()); // @E4C @P0C // Set the primary key table name request.setPrimaryKeyFileName(normalize(table), connection_.getConverter()); // @E4C @P0C // Set the Foreign key Information to Return Bitmap //@F4 As of base v4r4, host server can return primary and foreign key names. //@F4 Even this has nothing to do with lobs, borrow the constant as //@F4 it checks for v4r4. if (connection_.getVRM() >= JDUtilities.vrm440) //@F4A request.setForeignKeyReturnInfoBitmap(0xBBF80000); //@F4A else //@F4A request.setForeignKeyReturnInfoBitmap(0xBBE00000); //Get the long file name request.setFileShortOrLongNameIndicator (0xF0); // @KBA Long table names. //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache (row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); JDFieldMap[] maps = new JDFieldMap[14]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleDelimitedFieldMap (1); // pk schema //@PDC code to remove quotes maps[2] = new JDSimpleFieldMap (2); // pk table maps[3] = new JDSimpleFieldMap (3); // pk column maps[4] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[5] = new JDSimpleDelimitedFieldMap (4); // fk schema //@PDC code to remove quotes maps[6] = new JDSimpleFieldMap (5); // fk table maps[7] = new JDSimpleFieldMap (6); // fk column maps[8] = new JDSimpleFieldMap (7); // key seq maps[9] = new JDSimpleFieldMap (8); // update rule maps[10] = new JDSimpleFieldMap (9); // delete rule if (connection_.getVRM() >= JDUtilities.vrm440) //@F4A { maps[11] = new JDSimpleDelimitedFieldMap (10); //@F4A //@PDC code to remove quotes maps[12] = new JDSimpleDelimitedFieldMap (11); //@F4A //@PDC code to remove quotes } else { //@F4A maps[11] = new JDHardcodedFieldMap (new SQLVarchar(0, settings_), true, false); maps[12] = new JDHardcodedFieldMap (new SQLVarchar(0, settings_), true, false); } maps[13] = new JDHardcodedFieldMap (new Short ((short) importedKeyNotDeferrable)); JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } } catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "ExportedKeys", connection_, reply); //@in2 } /** Returns all of 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. @exception SQLException This exception is never thrown. **/ public String getExtraNameCharacters () throws SQLException { return "$@#"; } /** Returns the string used to quote SQL identifiers. @return The quote string. @exception SQLException This exception is never thrown. **/ public String getIdentifierQuoteString () throws SQLException { return "\""; } /** Returns a description of the primary key columns that are referenced by a table's foreign key columns. This is the primary keys imported by a table. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @return The ResultSets containing the description of the primary key columns that are referenced by a table's foreign key columns. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getImportedKeys (String catalog, String schema, String table) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator() +"SQLFOREIGNKEYS(?,?,?,?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, null); cs.setString(3, null); cs.setString(4, normalize(catalog)); cs.setString(5, normalize(schema)); cs.setString(6, normalize(table)); cs.setString(7, "DATATYPE='JDBC';IMPORTEDKEY=1; CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"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", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // pk catalog new SQLVarchar (128, settings_), // pk schema new SQLVarchar (128, settings_), // pk table new SQLVarchar (128, settings_), // pk column new SQLVarchar (128, settings_), // fk catalog new SQLVarchar (128, settings_), // fk schema new SQLVarchar (128, settings_), // fk table new SQLVarchar (128, settings_), // fk column new SQLSmallint (vrm, settings_), // key seq //@trunc3 new SQLSmallint (vrm, settings_), // update rule //@trunc3 new SQLSmallint (vrm, settings_), // delete rule //@trunc3 new SQLVarchar (128, settings_), // fk name new SQLVarchar (128, settings_), // pk name new SQLSmallint (vrm, settings_), // deferrability //@trunc3 }; int[] fieldNullables = {columnNullable, // pk catalog columnNullable, // pk schema columnNoNulls, // pk table columnNoNulls, // pk column columnNullable, // fk catalog columnNullable, // fk schema columnNoNulls, // fk table columnNoNulls, // fk column columnNoNulls, // key seq columnNoNulls, // update rule columnNoNulls, // delete rule columnNullable, // fk name columnNullable, // pk name columnNoNulls, // deferrability }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // table is null or empty string (table==null) || (table.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FOREIGN_KEY_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the foreign key file library name if (schema == null) { // use default SQL schema or qgpl request.setForeignKeyFileLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C } else request.setForeignKeyFileLibraryName(normalize(schema), connection_.getConverter()); // @E4C // Set the foreign key table name request.setForeignKeyFileName(normalize(table), connection_.getConverter()); // @E4C // Set the Foreign key Information to Return Bitmap //@F4 As of base v4r4, host server can return primary and foreign key names. //@F4 Even this has nothing to do with lobs, borrow the constant as //@F4 it checks for v4r4. if (connection_.getVRM() >= JDUtilities.vrm440) //@F4A request.setForeignKeyReturnInfoBitmap(0xBBF80000); //@F4A else //@F4A request.setForeignKeyReturnInfoBitmap(0xBBE00000); // This is not documented in the LIPI, but it happens to work! @E2A request.setFileShortOrLongNameIndicator(0xF0); // @E2A //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); JDFieldMap[] maps = new JDFieldMap[14]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleDelimitedFieldMap (1); // pk schema //@PDC code to remove quotes maps[2] = new JDSimpleFieldMap (2); // pk table maps[3] = new JDSimpleFieldMap (3); // pk column maps[4] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[5] = new JDSimpleDelimitedFieldMap (4); // fk schema //@PDC code to remove quotes maps[6] = new JDSimpleFieldMap (5); // fk table maps[7] = new JDSimpleFieldMap (6); // fk column maps[8] = new JDSimpleFieldMap (7); // key seq maps[9] = new JDSimpleFieldMap (8); // update rule maps[10] = new JDSimpleFieldMap (9); // delete rule if (connection_.getVRM() >= JDUtilities.vrm440) //@F4A { maps[11] = new JDSimpleDelimitedFieldMap (10); //@F4A //@PDC code to remove quotes maps[12] = new JDSimpleDelimitedFieldMap (11); //@F4A //@PDC code to remove quotes } else { //@F4A maps[11] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false); maps[12] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false); } maps[13] = new JDHardcodedFieldMap(new Short ((short) importedKeyNotDeferrable)); JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "ImportedKeys", connection_, reply); //@in2 } /** Returns a description of a table's indexes and statistics. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @param unique The value indicating if unique indexes should be returned. If true, only indexes for unique values is returned. If false, all indexes is returned. @param approximate The value indicating if the result is allowed to reflect approximate or out-of-date values. This value is ignored. @return The ResultSet containing the description of a table's indexes and statistics. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getIndexInfo (String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 String metadataSourceProperty = connection_.getProperties().getString(JDProperties.METADATA_SOURCE); //@pda 550 derived keys support. change to call sysibm.SQLSTATISTICS --start //@mdsp comment //note always call SP in v6r1 and later. ROI was lacking in this area. if (connection_.getVRM() >= JDUtilities.vrm610 || (metadataSourceProperty .equals(JDProperties.METADATA_SOURCE_STORED_PROCEDURE))) { short iUnique; short reserved = 0; if (unique) iUnique = 0; else iUnique = 1; //Set the library name if(schema != null) schema = normalize(schema); // Set the table name if(table != null) table = normalize(table); /* sysibm.SQLStatistics( CatalogName varchar(128), SchemaName varchar(128), TableName varchar(128), Unique Smallint, Reserved Smallint, Options varchar(4000)) */ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator () + "SQLSTATISTICS(?,?,?,?,?,?)"); cstmt.setString(1, normalize(catalog)); cstmt.setString(2, normalize(schema)); cstmt.setString(3, normalize(table)); cstmt.setShort(4, iUnique); cstmt.setShort(5, reserved); cstmt.setString(6, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cstmt.execute(); ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } //@pda 550 derived keys support. change to call sysibm.SQLSTATISTICS --end //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME", "TYPE", "ORDINAL_POSITION", "COLUMN_NAME", "ASC_OR_DESC", "CARDINALITY", "PAGES", "FILTER_CONDITION", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // schema new SQLVarchar (128, settings_), // table // when instantiating the non-unique small int // pass in a boolean and it will give it the // right value new SQLSmallint (vrm, settings_), // non-unique - boolean //@trunc3 new SQLVarchar (128, settings_), // index qualifier new SQLVarchar (128, settings_), // index name new SQLSmallint (vrm, settings_), // type //@trunc3 new SQLSmallint (vrm, settings_), // ordinal position //@trunc3 new SQLVarchar (128, settings_), // column name new SQLVarchar (1, settings_), // sort sequence new SQLInteger (vrm, settings_), // cardinality new SQLInteger (vrm, settings_), // pages //@trunc3 new SQLVarchar (128, settings_), // filter condition }; int[] fieldNullables = { columnNullable, // catalog columnNullable, // schema columnNoNulls, // table columnNoNulls, // non-unique columnNullable, // index qualifier columnNullable, // index name columnNoNulls, // type columnNoNulls, // ordinal position columnNullable, // column name columnNullable, // sort sequence columnNoNulls, // cardinality columnNoNulls, // pages columnNullable, // filter condition }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // table is null or empty string (table==null) || (table.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_INDEX_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the library name if (schema == null) { // use default SQL schema or qgpl request.setLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C } else request.setLibraryName(normalize(schema), connection_.getConverter()); // @E4C // Set the table name request.setFileName(normalize(table), connection_.getConverter()); // @E4C // Set the long file name indicator request.setFileShortOrLongNameIndicator (0xF0); // Long table names // Set the index unique rule if (unique) { // true - return indices for unique values request.setIndexUniqueRule(0x01); } else { request.setIndexUniqueRule(0x04); } // Set the Index Information to Return Bitmap request.setIndexReturnInfoBitmap(0xBDC00000); //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { // Put the data format into a row object JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); // Put the result data into a row cache JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. JDFieldMap[] maps = new JDFieldMap[13]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleFieldMap (1); // schema maps[2] = new JDSimpleFieldMap (2); // table maps[3] = new JDNonUniqueFieldMap (3); // non-unique maps[4] = new JDSimpleFieldMap (4); // index library name maps[5] = new JDSimpleFieldMap (5); // index name maps[6] = new JDHardcodedFieldMap(new Short ((short) tableIndexOther)); // type maps[7] = new JDSimpleFieldMap (7); // ordinal position maps[8] = new JDSimpleFieldMap (6); // column name maps[9] = new JDSimpleFieldMap (8); // sort sequence (collation) // cardinality unknown maps[10] = new JDHardcodedFieldMap(new Integer(-1)); // number of pages unknown maps[11] = new JDHardcodedFieldMap(new Integer(-1)); maps[12] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false); // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "IndexInfo", connection_, reply); //@in2 } // End of getIndexInfo //@G4A /** Returns the JDBC major version number. @return The JDBC major version number. @exception SQLException This exception is never thrown. @since Modification 5 **/ public int getJDBCMajorVersion () throws SQLException { return AS400JDBCDriver.JDBC_MAJOR_VERSION_; //@pdc } //@G4A /** Returns the JDBC minor version number. @return The JDBC minor version number. @exception SQLException This exception is never thrown. @since Modification 5 **/ public int getJDBCMinorVersion () throws SQLException { return AS400JDBCDriver.JDBC_MINOR_VERSION_; //@pdc } /** Returns the maximum length for an inline binary literal. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxBinaryLiteralLength () throws SQLException { return 32739; } /** Returns the maximum length for a catalog name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxCatalogNameLength () throws SQLException { return 10; } /** Returns the maximum length for a character literal. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxCharLiteralLength () throws SQLException { return 32739; } /** Returns the maximum length for a column name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxColumnNameLength () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm540) //@540 return 128; //@540 else return 30; } /** Returns the maximum number of columns in a GROUP BY clause. @return The maximum number of columns. @exception SQLException This exception is never thrown. **/ public int getMaxColumnsInGroupBy () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm610) //@550 max columns in group by support return 8000; //@550 else //@550 return 120; } /** Returns the maximum number of columns allowed in an index. @return The maximum number of columns. @exception SQLException This exception is never thrown. **/ public int getMaxColumnsInIndex () throws SQLException { return 120; } /** Returns the maximum number of columns in an ORDER BY clause. @return The maximum number of columns. @exception SQLException This exception is never thrown. **/ public int getMaxColumnsInOrderBy () throws SQLException { return 10000; } /** Returns the maximum number of columns in a SELECT list. @return The maximum number of columns. @exception SQLException This exception is never thrown. **/ public int getMaxColumnsInSelect () throws SQLException { return 8000; } /** Returns the maximum number of columns in a table. @return The maximum number of columns. @exception SQLException This exception is never thrown. **/ public int getMaxColumnsInTable () throws SQLException { return 8000; } /** Returns the number of active connections you can have at a time to this database. @return The maximum number of connections or 0 if no limit. @exception SQLException This exception is never thrown. **/ public int getMaxConnections () throws SQLException { // There is no limit. The specification does // not come right out and say "0 means no limit", // but that is how ODBC and many other parts // of JDBC work. return 0; } /** Returns the maximum cursor name length. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxCursorNameLength () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm610) //@550A return AS400JDBCStatement.MAX_CURSOR_NAME_LENGTH; else //@550A return AS400JDBCStatement.MAX_CURSOR_NAME_LENGTH_PRE_V6R1; //@550A } /** Returns the maximum length of an index. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxIndexLength () throws SQLException { return 2000; } /** Returns the maximum length of a procedure name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxProcedureNameLength () throws SQLException { return 128; } /** Returns the maximum length of a single row. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxRowSize () throws SQLException { return 32766; } /** Returns the maximum length allowed for a schema name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxSchemaNameLength () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm710) //@128sch return 128; //@128sch else //@128sch return 10; } /** Returns the maximum length of an SQL statement. @return The maximum length. @exception SQLException This exception is never thrown. **/ public int getMaxStatementLength () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm540) //@540 return 1048576; //@540 Statement text is always sent in 2 byte Unicode, so the maximum statement length in characters will always be 1 MB else //@540 return 32767; } /** Returns the number of active statements you can have open at one time. @return The maximum number of statements or 0 if no limit. @exception SQLException This exception is never thrown. **/ public int getMaxStatements () throws SQLException { return AS400JDBCConnectionImpl.MAX_STATEMENTS_; // @D3C } /** Returns the maximum length of a table name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxTableNameLength () throws SQLException { return 128; } /** Returns the maximum number of tables in a SELECT. @return The maximum number of tables. @exception SQLException This exception is never thrown. **/ public int getMaxTablesInSelect () throws SQLException { if (connection_.getVRM() >= JDUtilities.vrm540) // New in V5R4M0 @PDC return 1000; //@pdc else return 32; } /** Returns the maximum length of a user name. @return The maximum length (in bytes). @exception SQLException This exception is never thrown. **/ public int getMaxUserNameLength () throws SQLException { return 10; } /** Returns the list of supported math functions. @return The list of supported math functions, separated by commas. @exception SQLException This exception is never thrown. **/ public String getNumericFunctions () throws SQLException { // @J0A added try/catch because we are now sending the system VRM return JDEscapeClause.getNumericFunctions(connection_.getVRM()); // @J0M changed to send host version } /** Returns a description of the primary key columns. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the primary key columns. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getPrimaryKeys (String catalog, String schema, String table) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () +"SQLPRIMARYKEYS(?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schema)); cs.setString(3, normalize(table)); cs.setString(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "KEY_SEQ", "PK_NAME", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // pk catalog new SQLVarchar (128, settings_), // pk schema new SQLVarchar (128, settings_), // pk table new SQLVarchar (128, settings_), // pk column new SQLSmallint (vrm, settings_), // key seq //@trunc3 new SQLVarchar (128, settings_), // pk name }; int[] fieldNullables = {columnNullable, // pk catalog columnNullable, // pk schema columnNoNulls, // pk table columnNoNulls, // pk column columnNoNulls, // key seq columnNullable, // pk name }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // table is null or empty string (table==null) || (table.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_PRIMARY_KEY_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the primary key file library name if (schema == null) { // use default SQL schema or qgpl request.setPrimaryKeyFileLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C } else request.setPrimaryKeyFileLibraryName(normalize(schema), connection_.getConverter()); // @E4C // Set the primary key table name request.setPrimaryKeyFileName(normalize(table), connection_.getConverter()); // @E4C // Set the primary key Information to Return Bitmap request.setPrimaryKeyReturnInfoBitmap(0xBC000000); //@pdc // This is not documented in the LIPI, but it happens to work! @E2A request.setFileShortOrLongNameIndicator(0xF0); // @E2A //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache (row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. // boolean nullValue = true; // used when hardcoding null JDFieldMap[] maps = new JDFieldMap[6]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleDelimitedFieldMap (1); // pk schema //@PDC code to remove quotes maps[2] = new JDSimpleFieldMap (2); // pk table maps[3] = new JDSimpleFieldMap (3); // pk column maps[4] = new JDCharToShortFieldMap (4); // key seq //maps[5] = new JDHardcodedFieldMap (new SQLVarchar (0, settings_), true, false); //@pdd maps[5] = new JDSimpleFieldMap (5); //@pda // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request= null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "PrimaryKeys", connection_, reply); //@in2 } /** Returns a description of a catalog's stored procedure parameters and result columns.

Note: For this function to work with procedure names longer than 10 characters, the metadata source=1 property must be used on the connection. This is the default when connecting to a V7R1 or later system. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schemaPattern The schema name pattern. If null is specified, it will not be included in the selection criteria. If empty string is specified, an empty result set is returned. @param procedurePattern The procedure name pattern. If null is specified, it will not be included in the selection criteria. If empty string is specified, an empty result set is returned. @param columnPattern The column name pattern. If null is specified, it will not be included in the selection criteria. If empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the catalog's stored procedure parameters and result columns. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getProcedureColumns (String catalog, String schemaPattern, String procedurePattern, String columnPattern) throws SQLException { connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLPROCEDURECOLS(?,?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schemaPattern)); cs.setString(3, normalize(procedurePattern)); cs.setString(4, normalize(columnPattern)); /* ifdef JDBC40 cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4 endif */ /* ifndef JDBC40 */ cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); /* endif */ cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = { "PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME", "COLUMN_NAME", "COLUMN_TYPE", "DATA_TYPE", "TYPE_NAME", "PRECISION", "LENGTH", "SCALE", "RADIX", "NULLABLE", "REMARKS" }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // schema new SQLVarchar (128, settings_), // procedure new SQLVarchar (128, settings_), // column name new SQLSmallint (vrm, settings_), // column type //@trunc3 new SQLSmallint (vrm, settings_), // data type //@trunc3 new SQLVarchar (128, settings_), // type name new SQLInteger (vrm, settings_), // precision //@trunc3 new SQLInteger (vrm, settings_), // length //@trunc3 new SQLSmallint (vrm, settings_), // scale //@trunc3 new SQLInteger (vrm, settings_), // radix //@trunc3 new SQLSmallint (vrm, settings_), // nullable //@trunc3 new SQLVarchar (2000, settings_) // remarks }; int[] fieldNullables = { columnNullable, // catalog columnNullable, // schema columnNoNulls, // Procedure name columnNoNulls, // column name columnNoNulls, // column type columnNoNulls, // data type columnNoNulls, // type name columnNoNulls, // precision columnNoNulls, // length columnNoNulls, // scale columnNoNulls, // radix columnNoNulls, // nullable columnNoNulls // remarks }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schemaPattern != null) && (schemaPattern.length()==0)) || // procedure is not null and is empty string ((procedurePattern != null) && (procedurePattern.length()==0)) || // column is not null and is empty string ((columnPattern != null) && (columnPattern.length()==0))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // Parameters are valid, build request and send StringBuffer selectStmt = new StringBuffer(); selectStmt.append ("SELECT SPECIFIC_SCHEMA, SPECIFIC_NAME, PARAMETER_NAME, PARAMETER_MODE, "); selectStmt.append ("DATA_TYPE, NUMERIC_PRECISION, CHARACTER_MAXIMUM_LENGTH, NUMERIC_SCALE, "); selectStmt.append ("NUMERIC_PRECISION_RADIX, IS_NULLABLE, LONG_COMMENT "); selectStmt.append ("FROM QSYS2" + getCatalogSeparator() + "SYSPARMS "); // use . or / if (schemaPattern !=null) { JDSearchPattern schema = new JDSearchPattern (normalize(schemaPattern)); //@pdc normalize String schemaWhereClause = schema.getSQLWhereClause("SPECIFIC_SCHEMA"); selectStmt.append("WHERE " + schemaWhereClause); } if (procedurePattern !=null) { JDSearchPattern procedure = new JDSearchPattern (procedurePattern); if (schemaPattern!=null) { // Where clause already exists, add AND selectStmt.append (" AND "); } else { // Where clause does not exist, add WHERE selectStmt.append (" WHERE "); } String procedureWhereClause = procedure.getSQLWhereClause("SPECIFIC_NAME"); selectStmt.append(procedureWhereClause); } if (columnPattern!=null) { // if null, no where clause is sent JDSearchPattern column = new JDSearchPattern (columnPattern); if ((schemaPattern!=null) || (procedurePattern!=null)) { // Where clause already exists, add AND selectStmt.append (" AND "); } else { // Where clause does not exist, add WHERE selectStmt.append (" WHERE "); } String columnWhereClause = column.getSQLWhereClause("PARAMETER_NAME"); selectStmt.append(columnWhereClause); } // Add order by selectStmt.append ("ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION"); // Added ORDINAL_POSITION to fix JTOpen bug 3646, SYSPARMS table doesn't always have parameters in physical right order // Create statement object and do Execute Query AS400JDBCStatement statement_ = null; //@scan1 AS400JDBCResultSet serverResultSet = null; //@scan1 JDRowCache serverRowCache = null; try { statement_ = (AS400JDBCStatement)connection_.createStatement(); // caste needed serverResultSet = (AS400JDBCResultSet) statement_.executeQuery (selectStmt.toString()); serverRowCache = new JDSimpleRowCache(serverResultSet.getRowCache()); JDFieldMap[] maps = new JDFieldMap[13]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog()); maps[1] = new JDSimpleFieldMap (1); // schema maps[2] = new JDSimpleFieldMap (2); // procedure maps[3] = new JDHandleNullFieldMap (3, ""); // parameter name (col name) maps[4] = new JDParameterModeFieldMap(4); // Parameter mode (col type) maps[5] = new JDDataTypeFieldMap(5, 7, 6, 8, 0, connection_.getVRM(), connection_.getProperties()); // @M0C // data type - converts from string to short //@KKB pass 0 for ccsid maps[6] = new JDSimpleFieldMap (5); // type name maps[7] = new JDHandleNullFieldMap (6, new Integer (0)); // precision maps[8] = new JDHandleNullFieldMap (7, new Integer (0)); // length maps[9] = new JDHandleNullFieldMap (8, new Short ((short) 0)); // scale maps[10] = new JDHandleNullFieldMap (9, new Short ((short) 0)); // radix maps[11] = new JDNullableSmallintFieldMap(10); // nullable - is Nullable maps[12] = new JDHandleNullFieldMap (11, ""); // remarks - long comment JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); }finally //@scan1 { try{ if(serverResultSet != null) serverResultSet.close(); }catch(Exception e){ JDTrace.logException(this, "getProcedureColumns serverResultSet.close()", e); } //allow next close to execute if(statement_ != null) statement_.close (); } } // End of else build request and send } // End of try block catch (SQLException e) { // System.out.println(e); JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "ProcedureColumns", connection_, null); //@in2 } // End of getProcedureColumns /** Returns the description of the stored procedures available in a catalog. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schemaPattern The schema name pattern. If null is specified, it will not be included in the selection criteria. If empty string is specified, an empty result set is returned. @param procedurePattern The procedure name pattern. If null is specified, it will not be included in the selection criteria. If empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the stored procedures available in the catalog. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getProcedures (String catalog, String schemaPattern, String procedurePattern) throws SQLException { connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLPROCEDURES(?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schemaPattern)); cs.setString(3, normalize(procedurePattern)); cs.setString(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = { "PROCEDURE_CAT", "PROCEDURE_SCHEM", "PROCEDURE_NAME", "RESERVED1", "RESERVED2", "RESERVED3", "REMARKS", /* ifdef JDBC40 "PROCEDURE_TYPE", "SPECIFIC_NAME" //@JDBC40 endif */ /* ifndef JDBC40 */ "PROCEDURE_TYPE" /* endif */ }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // schema new SQLVarchar (128, settings_), // procedure new SQLInteger (vrm,settings_), // reserved //@trunc3 new SQLInteger (vrm,settings_), // reserved //@trunc3 new SQLInteger (vrm,settings_), // reserved //@trunc3 new SQLVarchar (2000, settings_), // remarks /* ifdef JDBC40 new SQLSmallint (vrm, settings_), // procedure type //@trunc3 new SQLVarchar (128, settings_) // specific name //@JDBC40 endif */ /* ifndef JDBC40 */ new SQLSmallint (vrm, settings_) // procedure type //@trunc3 /* endif */ }; int[] fieldNullables = { columnNullable, // Procedure catalog columnNullable, // Procedure schema columnNoNulls, // Procedure name columnNullable, // Reserved 1 columnNullable, // Reserved 2 columnNullable, // Reserved 3 columnNoNulls, // Remarks /* ifdef JDBC40 columnNoNulls, // Procedure type columnNoNulls // Specific name //@JDBC40 endif */ /* ifndef JDBC40 */ columnNoNulls // Procedure type /* endif */ }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if ((!isCatalogValid(catalog)) || // catalog is empty string // schema is not null and is empty string ((schemaPattern != null) && (schemaPattern.length()==0)) || // procedure is not null and is empty string ((procedurePattern!=null) && (procedurePattern.length()==0))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // Parameters are valid, build request and send StringBuffer selectStmt = new StringBuffer(); /* ifdef JDBC40 selectStmt.append ("SELECT ROUTINE_SCHEMA, ROUTINE_NAME, REMARKS, RESULTS, SPECIFIC_NAME ");//@PROC //@JDBC40 endif */ /* ifndef JDBC40 */ selectStmt.append ("SELECT ROUTINE_SCHEMA, ROUTINE_NAME, REMARKS, RESULTS ");//@PROC /* endif */ selectStmt.append ("FROM QSYS2" + getCatalogSeparator() + "SYSPROCS "); // use . or / if (schemaPattern !=null) { JDSearchPattern schema = new JDSearchPattern (schemaPattern); String schemaWhereClause = schema.getSQLWhereClause("ROUTINE_SCHEMA");//@PROC selectStmt.append("WHERE " + schemaWhereClause); } if (procedurePattern !=null) { JDSearchPattern procedure = new JDSearchPattern (procedurePattern); if (schemaPattern!=null) { // Where clause already exists, add AND selectStmt.append (" AND "); } else { // Where clause does not exist, add WHERE selectStmt.append (" WHERE "); } String procedureWhereClause = procedure.getSQLWhereClause("ROUTINE_NAME");//@PROC selectStmt.append(procedureWhereClause); } // Add order by selectStmt.append (" ORDER BY ROUTINE_SCHEMA, ROUTINE_NAME");//@PROC // Create statement object and do Execute Query AS400JDBCStatement statement_ = (AS400JDBCStatement)connection_.createStatement(); // caste needed AS400JDBCResultSet serverResultSet = (AS400JDBCResultSet) statement_.executeQuery (selectStmt.toString()); JDRowCache serverRowCache = new JDSimpleRowCache(serverResultSet.getRowCache()); statement_.close (); /* ifdef JDBC40 JDFieldMap[] maps = new JDFieldMap[9]; endif */ /* ifndef JDBC40 */ JDFieldMap[] maps = new JDFieldMap[8]; /* endif */ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog()); maps[1] = new JDSimpleFieldMap (1); // schema maps[2] = new JDSimpleFieldMap (2); // procedure maps[3] = new JDHardcodedFieldMap (new Integer (0)); maps[4] = new JDHardcodedFieldMap (new Integer (0)); maps[5] = new JDHardcodedFieldMap (new Integer (0)); maps[6] = new JDHandleNullFieldMap (3, ""); // remarks maps[7] = new JDProcTypeFieldMap (4); /* ifdef JDBC40 maps[8] = new JDSimpleFieldMap (5); //@jdbc40 endif */ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } // End of else build request and send } // End of try block catch (SQLException e) { // System.out.println(e); // e.printStackTrace(); // method on throwable object // @B1D JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); throw e; // @B1A } return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Procedures", connection_, null); //@in2 } /** Returns the DB2 for IBM i SQL term for "procedure". @return The term for "procedure". @exception SQLException This exception is never thrown. **/ public String getProcedureTerm () throws SQLException { return AS400JDBCDriver.getResource ("PROCEDURE_TERM",null); } //@G4A /** Retrieves the default holdability of this ResultSet object. Holdability is whether ResultSet objects are kept open when the statement is committed. @return Always ResultSet.HOLD_CURSORS_OVER_COMMIT. @exception SQLException This exception is never thrown. @since Modification 5 **/ public int getResultSetHoldability () throws SQLException { return AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT; } /** Returns the schema names available in this database. This will return a ResultSet with a list of all the libraries. @return The ResultSet containing the list of all the libraries. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getSchemas () throws SQLException { //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLTABLES(?,?,?,?,?)"); cs.setString(1, "%"); cs.setString(2, "%"); cs.setString(3, "%"); cs.setString(4, "%"); cs.setString(5, "DATATYPE='JDBC';GETSCHEMAS=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } return JDUtilities.getLibraries(this, connection_, settings_, false); //@DELIMa } /** Returns the DB2 for IBM i SQL term for "schema". @return The term for schema. @exception SQLException This exception is never thrown. **/ public String getSchemaTerm () throws SQLException { return AS400JDBCDriver.getResource ("SCHEMA_TERM",null); } /** Returns the string used to escape wildcard characters. This is the string that can be used to escape '_' or '%' in string patterns. @return The escape string. @exception SQLException This exception is never thrown. **/ public String getSearchStringEscape () throws SQLException { return JDSearchPattern.getEscape (); } /** Returns the list of all of the database's SQL keywords that are not also SQL-XXXX keywords. For JDK 1.5 and earlier, SQL-XXXX refers to SQL-92 keywords. For JDK 1.6 and later, SQL-XXXX refers to SQL-2003 keywords. @return The list of SQL keywords, separated by commas. @exception SQLException This exception is never thrown. **/ public String getSQLKeywords() throws SQLException { /* ifdef JDBC40 // Updated 2014/01/24 return "ACCORDING,ACCTNG,ACTION,ACTIVATE," + "ALIAS,ALLOW,APPEND,APPLNAME,ARRAY_AGG,ASC," + "ASSOCIATE,ATTRIBUTES,AUTONOMOUS,BEFORE,BIND," + "BIT,BUFFERPOOL,CACHE,CARDINALITY,CCSID,CL," + "CLUSTER,COLLECT,COLLECTION,COMMENT,COMPACT," + "COMPRESS,CONCAT,CONCURRENT,CONNECT_BY_ROOT," + "CONNECTION,CONSTANT,CONTAINS,CONTENT,COPY," + "COUNT,COUNT_BIG,CURRENT_SCHEMA,CURRENT_SERVER," + "CURRENT_TIMEZONE,DATA,DATABASE,DATAPARTITIONNAME," + "DATAPARTITIONNUM,DAYS,DBINFO,DBPARTITIONNAME," + "DBPARTITIONNUM,DB2GENERAL,DB2GENRL,DB2SQL," + "DEACTIVATE,DEFAULTS,DEFER,DEFINE,DEFINITION," + "DELETING,DENSERANK,DENSE_RANK,DESC,DESCRIPTOR," + "DIAGNOSTICS,DISABLE,DISALLOW,DOCUMENT,ENABLE," + "ENCRYPTION,ENDING,ENFORCED," + "EVERY,EXCEPTION,EXCLUDING,EXCLUSIVE,EXTEND," + "EXTRACT,FENCED,FIELDPROC,FILE,FINAL," + "FREEPAGE,GBPCACHE,GENERAL,GENERATED,GO," + "GOTO,GRAPHIC,HASH,HASHED_VALUE,HINT,HOURS," + "ID,IGNORE,IMPLICITLY,INCLUDE,INCLUDING," + "INCLUSIVE,INCREMENT,INDEX,INDEXBP,INF," + "INFINITY,INHERIT,INSERTING,INTEGRITY,ISOLATION," + "JAVA,KEEP,KEY,LABEL,LEVEL2,LINKTYPE," + "LOCALDATE,LOCATION,LOCATOR,LOCK,LOCKSIZE," + "LOG,LOGGED,LONG,MAINTAINED,MASK,MATCHED," + "MATERIALIZED,MAXVALUE,MICROSECOND,MICROSECONDS," + "MINPCTUSED,MINUTES,MINVALUE,MIXED,MODE," + "MONTHS,NAMESPACE,NAN,NEW_TABLE,NEXTVAL," + "NOCACHE,NOCYCLE,NODENAME,NODENUMBER,NOMAXVALUE," + "NOMINVALUE,NOORDER,NORMALIZED,NULLS,NVARCHAR," + "OBID,OLD_TABLE,OPTIMIZE,OPTION,ORDINALITY," + "ORGANIZE,OVERRIDING,PACKAGE,PADDED,PAGE," + "PAGESIZE,PART,PARTITIONED,PARTITIONING," + "PARTITIONS,PASSING,PASSWORD,PATH,PCTFREE," + "PERMISSION,PIECESIZE,PLAN,POSITION,PREVVAL," + "PRIOR,PRIQTY,PRIVILEGES,PROGRAM,PROGRAMID," + "QUERY,RANK,RCDFMT,READ,RECOVERY,REFRESH," + "RENAME,RESET,RESTART,RESULT_SET_LOCATOR,RID," + "ROUTINE,ROWNUMBER,ROW_NUMBER,RRN,RUN,SBCS," + "SCHEMA,SCRATCHPAD,SECONDS,SECQTY,SECURED," + "SEQUENCE,SESSION,SIMPLE,SKIP,SNAN,SOURCE," + "SQLID,STACKED,STARTING,STATEMENT,STOGROUP," + "SUBSTRING,SUMMARY,SYNONYM,TABLESPACE," + "TABLESPACES,THREADSAFE,TRANSACTION,TRANSFER," + "TRIM,TRIM_ARRAY,TRUNCATE,TYPE,UNIT," + "UPDATING,URI,USAGE,USE,USERID,VARIABLE," + "VARIANT,VCAT,VERSION,VIEW,VOLATILE,WAIT," + "WRAPPED,WRITE,WRKSTNNAME,XMLAGG,XMLATTRIBUTES," + "XMLCAST,XMLCOMMENT,XMLCONCAT,XMLDOCUMENT," + "XMLELEMENT,XMLFOREST,XMLGROUP,XMLNAMESPACES," + "XMLPARSE,XMLPI,XMLROW,XMLSERIALIZE,XMLTABLE," + "XMLTEXT,XMLVALIDATE,XSLTRANSFORM,XSROBJECT," + "YEARS,YES"; endif */ /* ifndef JDBC40 */ return "AFTER,ALIAS,ALLOW,APPLICATION,ASSOCIATE,ASUTIME,AUDIT," + // @J2M "AUX,AUXILIARY,BEFORE,BINARY," + // @J2A "BUFFERPOOL,CACHE,CALL,CALLED,CAPTURE,CARDINALITY,CCSID,CLUSTER," + // @J2A "COLLECTION,COLLID,COMMENT,CONCAT,CONDITION,CONTAINS,COUNT_BIG," + // @J2A "CURRENT_LC_CTYPE," + // @J2A "CURRENT_PATH,CURRENT_SERVER,CURRENT_TIMEZONE,CYCLE,DATA," + // @J2A "DATABASE,DAYS," + // @J2A "DB2GENERAL,DB2GENRL,DB2SQL,DBINFO,DEFAULTS,DEFINITION," + // @J2A "DETERMINISTIC," + // @J2A "DISALLOW,DO,DSNHATTR,DSSIZE,DYNAMIC,EACH,EDITPROC,ELSEIF," + // @J2A "ENCODING,END-EXEC1," + // @J2A "ERASE,EXCLUDING,EXIT,FENCED,FIELDPROC,FILE,FINAL,FREE,FUNCTION," + // @J2A "GENERAL," + // @J2A "GENERATED,GRAPHIC,HANDLER,HOLD,HOURS,IF,INCLUDING,INCREMENT," + // @J2A "INDEX," + // @J2A "INHERIT,INOUT,INTEGRITY,ISOBID,ITERATE,JAR,JAVA,LABEL,LC_CTYPE," + // @J2A "LEAVE," + // @J2A "LINKTYPE,LOCALE,LOCATOR,LOCATORS,LOCK,LOCKMAX,LOCKSIZE,LONG,LOOP," + // @J2A "MAXVALUE,MICROSECOND,MICROSECONDS,MINUTES,MINVALUE,MODE,MODIFIES," + // @J2A "MONTHS," + // @J2A "NEW,NEW_TABLE,NOCACHE,NOCYCLE,NODENAME,NODENUMBER,NOMAXVALUE," + // @J2A "NOMINVALUE," + // @J2A "NOORDER,NULLS,NUMPARTS,OBID,OLD,OLD_TABLE,OPTIMIZATION,OPTIMIZE," + // @J2A "OUT,OVERRIDING,PACKAGE,PARAMETER,PART,PARTITION,PATH,PIECESIZE," + // @J2A "PLAN," + // @J2A "PRIQTY,PROGRAM,PSID,QUERYNO,READS,RECOVERY,REFERENCING,RELEASE," + // @J2A "RENAME,REPEAT,RESET,RESIGNAL,RESTART,RESULT,RESULT_SET_LOCATOR," + // @J2A "RETURN," + // @J2A "RETURNS,ROUTINE,ROW,RRN,RUN,SAVEPOINT,SCRATCHPAD,SECONDS,SECQTY," + // @J2A "SECURITY,SENSITIVE,SIGNAL,SIMPLE,SOURCE,SPECIFIC,SQLID,STANDARD," + // @J2A "START,STATIC,STAY,STOGROUP,STORES,STYLE,SUBPAGES,SYNONYM,SYSFUN," + // @J2A "SYSIBM," + // @J2A "SYSPROC,SYSTEM,TABLESPACE,TRIGGER,TYPE,UNDO,UNTIL,VALIDPROC," + // @J2A "VARIABLE," + // @J2A "VARIANT,VCAT,VOLUMES,WHILE,WLM,YEARS"; // @J2A /* endif */ } //@G4A /** Indicates whether the SQLSTATEs returned by SQLException.getSQLState is X/Open SQL CLI or SQL99. @return Always sqlStateSQL99. @exception SQLException This exception is never thrown. @since Modification 5 **/ public int getSQLStateType () throws SQLException { return AS400JDBCDatabaseMetaData.sqlStateSQL99; } /** Returns the list of supported string functions. @return The list of supported string functions, separated by commas. @exception SQLException This exception is never thrown. **/ public String getStringFunctions () throws SQLException { // @J0A added try/catch because we are now sending the system VMR return JDEscapeClause.getStringFunctions(connection_.getVRM()); // @J0M changed to send host version } //@G4A /** Returns a ResultSet containing descriptions of the table hierarchies in a schema. This method only applies to the attributes of a structured type. Distinct types are stored in the datatypes catalog, not the attributes catalog. Since DB2 for IBM i does not support structured types at this time, an empty ResultSet will always be returned for calls to this method. @param catalog The catalog name. @param schemaPattern The schema name pattern. @param typeNamePattern The type name pattern. @return The empty ResultSet @exception SQLException This exception is never thrown. @since Modification 5 **/ public ResultSet getSuperTables (String catalog, String schemaPattern, String typeNamePattern) throws SQLException { // We return an empty result set because this is not supported by our driver Statement statement = connection_.createStatement(); return statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " + "VARCHAR('2', 128) AS TYPE_SCHEM, " + "VARCHAR('3', 128) AS TYPE_NAME, " + "VARCHAR('4', 128) AS SUPERTYPE_NAME " + "FROM QSYS2" + getCatalogSeparator() + "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY "); } //@G4A /** Returns a ResultSet containing descriptions of user-defined type hierarchies in a schema. This method only applies to the attributes of a structured type. Distinct types are stored in the datatypes catalog, not the attributes catalog. Since DB2 for IBM i does not support structured types at this time, an empty ResultSet will always be returned for calls to this method. @param catalog The catalog name. @param schemaPattern The schema name pattern. @param typeNamePattern The type name pattern. @return The empty result set @exception SQLException This exception is never thrown. @since Modification 5 **/ public ResultSet getSuperTypes (String catalog, String schemaPattern, String typeNamePattern) throws SQLException { // We return an empty result set because this is not supported by our driver Statement statement = connection_.createStatement(); return statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " + "VARCHAR('2', 128) AS TYPE_SCHEM, " + "VARCHAR('3', 128) AS TYPE_NAME, " + "VARCHAR('4', 128) AS SUPERTYPE_CAT, " + "VARCHAR('5', 128) AS SUPERTYPE_SCHEM, " + "VARCHAR('6', 128) AS SUPERTYPE_NAME " + "FROM QSYS2" + getCatalogSeparator() + "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY "); } /** Returns the list of supported system functions. @return The list of supported system functions, separated by commas. @exception SQLException This exception is never thrown. **/ public String getSystemFunctions () throws SQLException { // @J0A added try/catch because we are now sending the system VMR return JDEscapeClause.getSystemFunctions(connection_.getVRM()); // @J0M changed to send host version } /** Returns the description of the access rights for each table available in a catalog. Note that a table privilege applies to one or more columns in a table. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schemaPattern The schema name pattern. If the "metadata source" connection property is set to 0 and null is specified, no value is sent to the system and the default of *USRLIBL is used. If the "metadata source" connection property is set to 1 and null is specified, then information from all schemas will be returned. If empty string is specified, an empty result set is returned. @param tablePattern The table name. If null is specified, no value is sent to the system and the system default of *ALL is used. If empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the access rights for each table available in the catalog. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getTablePrivileges (String catalog, String schemaPattern, String tablePattern) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); // int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLTABLEPRIVILEGES(?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schemaPattern)); cs.setString(3, normalize(tablePattern)); cs.setString(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //----------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "GRANTOR", "GRANTEE", "PRIVILEGE", "IS_GRANTABLE", }; SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog new SQLVarchar (128, settings_), // library new SQLVarchar (128, settings_), // table new SQLVarchar (128, settings_), // grantor new SQLVarchar (128, settings_), // grantee new SQLVarchar (128, settings_), // privilege new SQLVarchar (3, settings_), // is_grantable }; int[] fieldNullables = {columnNullable, // catalog columnNullable, // library columnNoNulls, // table columnNullable, // grantor columnNoNulls, // grantee columnNoNulls, // privilege columnNullable, // is_grantable }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if (!isCatalogValid(catalog) || // catalog is empty string // schema is not null and is empty string ((schemaPattern != null) && (schemaPattern.length()==0)) || // table is not null and is empty string ((tablePattern != null) && (tablePattern.length()==0))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FILE_INFO, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the library name and search pattern indicator // If null, do not set parameter. The system default // value of *USRLIBL is used. if (schemaPattern!=null) { JDSearchPattern schema = new JDSearchPattern(schemaPattern); request.setLibraryName(normalize(schema.getPatternString()), connection_.getConverter()); // @E4C request.setLibraryNameSearchPatternIndicator(schema.getIndicator()); } // Set the table name and search pattern indicator // If null, do not set parameter. The system default // value of *ALL is used. if (tablePattern!=null) { JDSearchPattern table = new JDSearchPattern(tablePattern); request.setFileName(normalize(table.getPatternString()),connection_.getConverter()); // @E4C request.setFileNameSearchPatternIndicator(table.getIndicator()); } request.setFileShortOrLongNameIndicator (0xF0); // Long table names request.setFileReturnInfoBitmap (0xA1000000); // Return bitmap // Order the results by table type, table schema, table name request.setFileInfoOrderByIndicator (2); //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); // Put the data format into a row object JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); // Put the result data into a row cache JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache (row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. JDFieldMap[] maps = new JDFieldMap[7]; maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ()); maps[1] = new JDSimpleFieldMap (1); // library maps[2] = new JDSimpleFieldMap (2); // table maps[3] = new JDHardcodedFieldMap ("", true, false); // grantor maps[4] = new JDHardcodedFieldMap (getUserName ()); // grantee - return userid maps[5] = new JDPrivilegeFieldMap (3); // privilege maps[6] = new JDHardcodedFieldMap ("", true, false); // is_grantable // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } finally { if (request != null) { request.returnToPool(); request = null;} // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "TablePrivileges", connection_, reply); //@in2 //@G4C } /** Returns the description of the tables available in a catalog. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schemaPattern The schema name pattern. If the "metadata source" connection property is set to 0 and null is specified, no value is sent to the system and the default of *USRLIBL is used. If the "metadata source" connection property is set to 1 and null is specified, then information from all schemas will be returned. If an empty string is specified, an empty result set is returned. @param tablePattern The table name pattern. If null is specified, no value is sent to the system and the system default of *ALL is used. If empty string is specified, an empty result set is returned. @param tableTypes The list of table types to include, or null to include all table types. Valid types are: TABLE, VIEW, SYSTEM TABLE, MATERIALIZED QUERY TABLE, and ALIAS. @return The ResultSet containing the description of the tables available in the catalog. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getTables (String catalog, String schemaPattern, String tablePattern, String tableTypes[]) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen ();// Verify that a connection // is available for use. Exception // is thrown if not available // int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call and Native logic if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { // Handle the old schema pattern of *ALLUSR by changing // it to null. This will allow the SQuirreL JDBC client to // work without changing their logic. Otherwise, they // would need to know that, by default, *ALLUSR is supported // when running to V6R1 with metadata source=0 and not // supported when running to V7R1 and later with metatdata source=1. if ("*ALLUSR".equals(schemaPattern)) { schemaPattern = null; } // Handle processing the array of table types. //bite the bullet and follow Native JDBC logic boolean rsEmpty = false; String typeString = EMPTY_STRING; if (!rsEmpty) { int i; int stringsInList = 0; if (tableTypes != null) { for (i = 0; i < tableTypes.length; i++) { String check = tableTypes[i]; if ((check.equalsIgnoreCase(VIEW)) || (check.equalsIgnoreCase(TABLE)) || (check.equalsIgnoreCase(SYSTEM_TABLE)) || (check.equalsIgnoreCase(ALIAS)) || (check.equalsIgnoreCase(SYNONYM)) || (check.equalsIgnoreCase(MQT))) { if (check.equalsIgnoreCase(SYNONYM)) { check = ALIAS; } stringsInList++; if (stringsInList > 1) typeString = typeString.concat(","); typeString = typeString.concat(check); } } // If there were no valid types, ensure an empty result set. if (stringsInList == 0) rsEmpty = true; } } // If an empty result set is to be generated, produce the values to // do so here. if (rsEmpty) { schemaPattern = FAKE_VALUE; tablePattern = FAKE_VALUE; typeString = typeString.concat(TABLE); //@scan1 } CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator () + "SQLTABLES(?,?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schemaPattern)); cs.setString(3, normalize(tablePattern)); cs.setString(4, normalize(typeString)); cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); try { cs.execute(); // Catch a resource limit error for applications that are not // closing result sets. } catch (SQLException e) { if (e.getErrorCode() == -7049) { // Cleanup by running the GC and waiting System.gc(); try { Thread.sleep(1000); } catch (InterruptedException e1) { } // Retry cs.execute(); } else { throw e; } } ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //----------------------------------------------------- // Set up the result set in the format required by JDBC //----------------------------------------------------- boolean isJDBC3 = true; String[] fieldNames = null; //@F2C SQLData[] sqlData = null; //@F2C int[] fieldNullables = null; //@F2C if (!isJDBC3) //@F2A { fieldNames = new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS"}; sqlData = new SQLData[] { new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (254, settings_)}; fieldNullables = new int[] {columnNullable, // Table catalog columnNullable, // Table schema columnNoNulls, // Table name columnNoNulls, // Table type columnNoNulls}; // Remarks } else { fieldNames = new String[] { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT", //@G4A "TYPE_SCHEM", //@G4A "TYPE_NAME", //@G4A "SELF_REFERENCING_COL_NAME", //@G4A "REF_GENERATION"}; //@G4A sqlData = new SQLData[] { new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (128, settings_), new SQLVarchar (254, settings_), new SQLVarchar (128, settings_), //@G4A new SQLVarchar (128, settings_), //@G4A new SQLVarchar (128, settings_), //@G4A new SQLVarchar (128, settings_), //@G4A new SQLVarchar (128, settings_)}; //@G4A fieldNullables = new int[] {columnNullable, // Table catalog columnNullable, // Table schema columnNoNulls, // Table name columnNoNulls, // Table type columnNoNulls, // Remarks columnNullable, // Types catalog //@G4A columnNullable, // Types schema //@G4A columnNullable, // Type name //@G4A columnNullable, // Self referencing column name //@G4A columnNullable}; // Reference generation //@G4A } JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows that // are readable one at a time try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if (!isCatalogValid(catalog) || // catalog is empty string // schema is not null and is empty string ((schemaPattern != null) && (schemaPattern.length()==0)) || // table is not null and is empty string ((tablePattern != null) && (tablePattern.length()==0))) { // Return empty result set rowCache = new JDSimpleRowCache(formatRow); } else { // schema, table, and catalog are valid, create and send request //------------------------------------------------------- // Set the file attribute parm of the Retrieve File // Information (ROI) function based on the types array // provided. ROI uses the following values: // '0001'x = all files // '0002'x = physical files and alias files // '0003'x = logical files and alias files // '0004'x = tables and alias files // '0005'x = views and alias files // '0006'x = system tables // '0007'x = tables and views and alias files // '0008'x = tables and system tables and alias files // '0009'x = views and system tables and alias files // '000A'x = alias files //@K1A // '000B'x = tables and materialized query tables //@K1A // '000C'x = views and materialized query tables //@K1A // '000D'x = system tables and materialized query tables //@K1A // '000E'x = tables, views, and materialized query tables //@K1A // '000F'x = tables, system tables, and materialized query tables //@K1A // '0010'x = views, system tables, and materizlized query tables //@K1A // '0011'x = materialized query tables //@K1A // // Options '000B'x - '0011'x are for V5R3 or higher systems // // If null is specified, file attributes is set to 1. // // If none of the above values are specified, file // attribute is set to -1 and an empty result set will // be created. No request is sent to the system. //-------------------------------------------------------- int fileAttribute; boolean needToRemoveAliases = true; if (tableTypes != null) { boolean typeTable = false; // false = don't include table type boolean typeView = false; boolean typeSystemTable = false; boolean typeMQTable = false; boolean typeAlias = false; // Walk thru table types to determine which ones we need to include for (int i = 0; i < tableTypes.length; ++i) { if (tableTypes[i].equalsIgnoreCase ("TABLE")) typeTable = true; // Include tables else if (tableTypes[i].equalsIgnoreCase ("VIEW")) typeView = true; // Include views else if (tableTypes[i].equalsIgnoreCase ("SYSTEM TABLE")) typeSystemTable = true; // Include system tables else if (tableTypes[i].equalsIgnoreCase ("MATERIALIZED QUERY TABLE") && connection_.getVRM() >= JDUtilities.vrm530) //@K1A typeMQTable = true; //@K1A else if(tableTypes[i].equalsIgnoreCase("ALIAS")) typeAlias = true; } // end of for loop if(typeAlias) needToRemoveAliases = false; if (typeTable) { if (typeView) { if (typeSystemTable) fileAttribute = 1; // All else if(typeMQTable) //@K1A { fileAttribute = 14; //tables, views, and MQT's //@K1A needToRemoveAliases = false; } else fileAttribute = 7; // Tables and views } else if(typeSystemTable) //@K1A Not Views { //@K1A if(typeMQTable) //@K1A { fileAttribute = 15; //@K1A needToRemoveAliases = false; // no aliases are returned } else //@K1A fileAttribute = 8; // Tables and system tables } //@K1A else if(typeMQTable) //@K1A Not Views and not system tables { //@K1A fileAttribute = 11; //@K1A needToRemoveAliases = false; // no aliases are returned } //@K1A else fileAttribute = 4; // Tables } // end of if typeTable else if(typeMQTable) //@K1A { //@K1A if(typeView) //@K1A { //@K1A if(typeSystemTable) //@K1A fileAttribute = 16; //views, system tables, and MQT's //@K1A else //@K1A fileAttribute = 12; //views and MQT's //@K1A } //@K1A else if(typeSystemTable) //@K1A fileAttribute = 13; //system tables and MQT's //@K1A else //@K1A fileAttribute = 17; //MQT's //@K1A needToRemoveAliases = false; //no aliases are returned } //@K1A else { // Not tables if (typeView) { if (typeSystemTable) fileAttribute = 9; // Views and system tables else fileAttribute = 5; // Views } else { if (typeSystemTable) { fileAttribute = 6; // System tables needToRemoveAliases = false; // no aliases are returned } else if(typeAlias && connection_.getVRM() >= JDUtilities.vrm430) // Aliases are only supported on V4R3 and higher fileAttribute = 10; else fileAttribute = -1; // Unknown type // Will return empty results } } // End of not tables else } // End of if tables != nulls else { // Table types was set to null which implies all // types are to be returned fileAttribute = 1; // All } //------------------------------------------------ // Create the request to Retrieve File Information //------------------------------------------------ if (fileAttribute != -1) { // If -1, return empty set // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_FILE_INFO, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA,0); //-------------------------------------------------- // Set the parameters for the request //-------------------------------------------------- // Set the Library Name and Library Name Search Pattern parameters // If null, do not set parameter. The system default value of // *USRLIBL is used. if (schemaPattern != null) { // use default SQL schema or qgpl JDSearchPattern schema = new JDSearchPattern(schemaPattern); request.setLibraryName (normalize(schema.getPatternString()), connection_.getConverter()); // @E4C request.setLibraryNameSearchPatternIndicator(schema.getIndicator()); } // Set the Table Name and Table Name Search Pattern parameters // If null, do not set parameter. The system default value of // *ALL is used. if (tablePattern!=null) { JDSearchPattern table = new JDSearchPattern(tablePattern); request.setFileName (normalize(table.getPatternString()), connection_.getConverter()); // @E4C request.setFileNameSearchPatternIndicator(table.getIndicator()); } // Set other parameters request.setFileShortOrLongNameIndicator (0xF0); // Long table names. request.setFileAttribute (fileAttribute); // Set the information to return. Always return the // library name, file name, and file attribute (ODBC // type). Also return either the remarks or the file // text depending on what the "remarks" attribute // is set to. // Get the current value for the "remarks" property // and check to see if it is sql or system // connection_.getProperties() returns the JDProperties // object if (connection_.getProperties().equals (JDProperties.REMARKS, JDProperties.REMARKS_SQL)) { request.setFileReturnInfoBitmap (0xF0000000); // return remarks } else { request.setFileReturnInfoBitmap (0xB4000000); // return text } // Order the results by table type, table schema, table name // This is the same as ordering by tables on the system request.setFileInfoOrderByIndicator (2); //------------------------------------------------------- // Send the request and cache all results from the system //------------------------------------------------------- reply = connection_.sendAndReceive (request); // Check for errors - throw exception if errors // were returned int errorClass = reply.getErrorClass(); if (errorClass != 0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data // The result data is parsed via JDServerRow getData DBDataFormat dataFormat = reply.getDataFormat (); DBData resultData = reply.getResultData (); if (resultData != null) { // If the user didn't request aliases if(needToRemoveAliases) parseResultData(resultData, dataFormat); // Put the data format into a row format. Handles data types JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); // Put the result data into a row cache // ServerRowCache needs rowFormat to get offset and other info // Only need this with this type of row cache (not with simple) JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // This is not actually moving data, it just sets up the mapping JDFieldMap[] maps = null; //@F2C if (!isJDBC3) //@F2A maps = new JDFieldMap[5]; else maps = new JDFieldMap[10]; if (connection_.getProperties().equals (JDProperties.REMARKS, JDProperties.REMARKS_SQL)) { maps[0] = new JDHardcodedFieldMap (connection_.getCatalog()); maps[1] = new JDSimpleFieldMap (1); // schema // @A3C @E4C maps[2] = new JDSimpleFieldMap (3); // table maps[3] = new JDTableTypeFieldMap (4); // table type maps[4] = new JDSimpleFieldMap (2); // remarks //@G4A The below fields will all return null. We have distinct types //@G4A instead of abstract types here, so a request returns no //@G4A type information. if (isJDBC3) { maps[5] = new JDHardcodedFieldMap ("", true, false); // types catalog //@G4A maps[6] = new JDHardcodedFieldMap ("", true, false); // types schema //@G4A maps[7] = new JDHardcodedFieldMap ("", true, false); // type name //@G4A maps[8] = new JDHardcodedFieldMap ("", true, false); // self referencing col name //@G4A maps[9] = new JDHardcodedFieldMap ("", true, false); // ref generation //@G4A } } else { // Get file text instead of remarks maps[0] = new JDHardcodedFieldMap (connection_.getCatalog()); maps[1] = new JDSimpleFieldMap (1); // schema // @A3C @E4C maps[2] = new JDSimpleFieldMap (2); // table maps[3] = new JDTableTypeFieldMap (3); // table type maps[4] = new JDSimpleFieldMap (4); // File text //@G4A The below fields will all return null. We have distinct types //@G4A instead of abstract types here, so a request returns no //@G4A type information. if (isJDBC3) { maps[5] = new JDHardcodedFieldMap ("", true, false); // types catalog //@G4A maps[6] = new JDHardcodedFieldMap ("", true, false); // types schema //@G4A maps[7] = new JDHardcodedFieldMap ("", true, false); // type name //@G4A maps[8] = new JDHardcodedFieldMap ("", true, false); // self referencing col name //@G4A maps[9] = new JDHardcodedFieldMap ("", true, false); // ref generation //@G4A } } JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache(formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of if file attribute != -1 else { // result set should be empty. rowCache = new JDSimpleRowCache(formatRow); } } // End of else to create and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Tables", connection_, reply); //@in2 } // Parses the result data from the system to determine if any aliases were returned. void parseResultData(DBData resultData, DBDataFormat dataFormat) { try{ byte[] rawBytes = resultData.getRawBytes(); int rowCount = resultData.getRowCount(); int columnOffset = dataFormat.getFieldLength(0); // schema columnOffset += dataFormat.getFieldLength(1); // table int tableTypeLength = dataFormat.getFieldLength(2); // table type SQLChar tableType = new SQLChar(tableTypeLength, settings_); // create an sql char ojbect to get the table type int aliasCount = 0; ConvTable ccsidConverter = connection_.getConverter(dataFormat.getFieldCCSID(2)); for(int i=0; i= JDUtilities.vrm530))) //@5WXVJX typeSamples.addElement(new SQLCharForBitData(32765, settings_)); // @M0A typeSamples.addElement(new SQLDate(settings_, -1)); // @D0C @550C typeSamples.addElement(new SQLDecimal(31, 31, settings_, connection_.getVRM(), connection_.getProperties())); // @M0C typeSamples.addElement(new SQLDouble(settings_)); // @D0C typeSamples.addElement(new SQLFloat(settings_)); // @D0C typeSamples.addElement(new SQLGraphic(16382, settings_, -1)); //@cca1 typeSamples.addElement(new SQLInteger(vrm,settings_)); //@trunc3 // @D0C typeSamples.addElement(new SQLNumeric(31, 31, settings_, connection_.getVRM(), connection_.getProperties())); // @M0C typeSamples.addElement(new SQLReal(settings_)); // @D0C typeSamples.addElement(new SQLSmallint(vrm,settings_)); //@trunc3 // @D0C typeSamples.addElement(new SQLTime(settings_, -1)); // @D0C @550C if (connection_.getVRM() > JDUtilities.vrm710) { /* @H3A*/ typeSamples.addElement(new SQLTimestamp(32, settings_)); // @D0C } else { typeSamples.addElement(new SQLTimestamp(26, settings_)); // @D0C } //typeSamples.addElement(new SQLLongVarchar(32739, settings_)); //Change to report LONG VARCHAR as VARCHAR to be consistent with other clients. typeSamples.addElement(new SQLLongVargraphic(16369, settings_, -1)); typeSamples.addElement(new SQLLongVarcharForBitData(32739, settings_)); typeSamples.addElement(new SQLVarchar(32739, settings_)); // @D0C if((connection_.getVRM() < JDUtilities.vrm530) || (translateHexAsChar && (connection_.getVRM() >= JDUtilities.vrm530))) //@5WXVJX typeSamples.addElement(new SQLVarcharForBitData(32739, settings_)); // @M0A typeSamples.addElement(new SQLVargraphic(16369, settings_, -1)); //@cca1 if (connection_.getVRM() >= JDUtilities.vrm440) { // @B4D B5A @D0C typeSamples.addElement(new SQLDatalink(32717, settings_)); typeSamples.addElement(new SQLBlob(MAX_LOB_LENGTH, settings_)); // @B4D B5A @D0C //@xml3 typeSamples.addElement(new SQLClob(MAX_LOB_LENGTH, settings_)); // @B4D B5A @D0C @E1C //@xml3 typeSamples.addElement(new SQLDBClob(1073741822, settings_)); } // @B4D B5A if (connection_.getVRM() >= JDUtilities.vrm450) // @D0A typeSamples.addElement(new SQLBigint(vrm, settings_)); //@trunc3 // @D0A // @M0A - added support for binary, varbinary, and rowid data types if(connection_.getVRM() >= JDUtilities.vrm520) { typeSamples.addElement(new SQLRowID(settings_)); } if(connection_.getVRM() >= JDUtilities.vrm530) { if(!translateHexAsChar) //@5WXVJX { typeSamples.addElement(new SQLBinary(32765, settings_)); typeSamples.addElement(new SQLVarbinary(32739, settings_)); } } if(connection_.getVRM() >= JDUtilities.vrm610) //@dfa { //@dfa //note that on hostserver both 16 and 34 are one type (stored proc returns one type) typeSamples.addElement(new SQLDecFloat34( settings_, connection_.getVRM(), connection_.getProperties())); //@dfa } //@dfa // @M0A - end new support int numberOfTypes = typeSamples.size(); // @D0C int numberOfFields = sqlData.length; Object[][] data = new Object[numberOfTypes][]; boolean[][] nulls = new boolean[numberOfTypes][]; boolean[][] dataMappingErrors = new boolean[numberOfTypes][]; for (int i = 0; i < numberOfTypes; ++i) { data[i] = new Object[numberOfFields]; nulls[i] = new boolean[numberOfFields]; dataMappingErrors[i] = new boolean[numberOfFields]; SQLData typeSample = (SQLData) typeSamples.elementAt(i); // @D0C data[i][0] = typeSample.getTypeName (); // @D0C data[i][1] = new Short ((short) typeSample.getType ()); // @D0C data[i][2] = new Integer (typeSample.getMaximumPrecision()); // @D0C String literalPrefix = typeSample.getLiteralPrefix (); // @D0C if (literalPrefix == null) { data[i][3] = ""; nulls[i][3] = true; } else data[i][3] = literalPrefix; String literalSuffix = typeSample.getLiteralSuffix (); // @D0C if (literalSuffix == null) { data[i][4] = ""; nulls[i][4] = true; } else data[i][4] = literalSuffix; String createParameters = typeSample.getCreateParameters (); // @D0C if (createParameters == null) { data[i][5] = ""; nulls[i][5] = true; } else data[i][5] = createParameters; data[i][6] = new Short ((short) typeNullable); data[i][7] = new Boolean (typeSample.isText ()); // @D0C data[i][8] = new Short ((short) typeSearchable); data[i][9] = new Boolean (! typeSample.isSigned ()); // @D0C data[i][10] = new Boolean (false); data[i][11] = new Boolean (false); String localName = typeSample.getLocalName (); // @D0C if (localName == null) { data[i][12] = ""; nulls[i][12] = true; } else data[i][12] = localName; data[i][13] = new Short ((short) typeSample.getMinimumScale ()); // @D0C data[i][14] = new Short ((short) typeSample.getMaximumScale ()); // @D0C data[i][15] = new Integer (0); data[i][16] = new Integer (0); data[i][17] = new Integer (typeSample.getRadix ()); // @D0C } JDSimpleRowCache rowCache = new JDSimpleRowCache(formatRow, data, nulls, dataMappingErrors); return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Type Info", connection_, null); //@in2 } // JDBC 2.0 /** Returns the description of the user-defined types available in a catalog. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schemaPattern The schema name pattern. If the "metadata source" connection property is set to 0 and null is specified, no value is sent to the system and the default of *USRLIBL is used. If the "metadata source" connection property is set to 1 and null is specified, then information from all schemas will be returned. If an empty string is specified, an empty result set is returned. @param typeNamePattern The type name pattern. If null is specified, no value is sent to the system and the system default of *ALL is used. If empty string is specified, an empty result set is returned. @param types The list of user-defined types to include, or null to include all user-defined types. Valid types are: JAVA_OBJECT, STRUCT, and DISTINCT. @return The ResultSet containing the description of the user-defined available in the catalog. @exception SQLException If the connection is not open or an error occurs. **/ // // Implementation note: // // 1. I was worried about cases where one distinct type is created // based on another distinct type. This would cause problems // because the source type would no longer identify a system // predefined type and we would have to follow the chain until // we found a system predefined type. // // It turns out that this is not an issue. In the "JDBC Tutorial and // Reference", section 3.5.5 "Creating a DISTINCT type", it says: // "A DISTINCT type is always based on another data type, which must // be a predefined type. ... a DISTINCT type cannot be based // on a UDT." ("UDT" means user-defined type.) // So we can make the assumption that the source type // always identifies a system predefined type. // public ResultSet getUDTs (String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { connection_.checkOpen (); //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator()+ "SQLUDTS(?,?,?,?,?)"); cs.setString(1, normalize(catalog)); cs.setString(2, normalize(schemaPattern)); cs.setString(3, normalize(typeNamePattern)); StringBuffer typesStringBuffer = new StringBuffer(); int stringsInList = 0; if (types != null) { for (int i = 0; i < types.length; i++) { if (stringsInList > 0) { typesStringBuffer.append(","); } typesStringBuffer.append(types[i]); stringsInList++; } } cs.setString(4, typesStringBuffer.toString()); /* ifdef JDBC40 cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4 endif */ /* ifndef JDBC40 */ cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); /* endif */ cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } int vrm = connection_.getVRM(); //@trunc3 boolean isJDBC3 = true; //@F2A @j4a String[] fieldNames = null; //@F2C SQLData[] sqlData = null; //@F2C int[] fieldNullables = null; //@F2C // Set up the result set in the format required by JDBC 3.0 fieldNames = new String[] { "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "CLASS_NAME", "DATA_TYPE", "REMARKS", "BASE_TYPE" //@G4A }; sqlData = new SQLData[] { new SQLVarchar (128, settings_), // type catalog new SQLVarchar (128, settings_), // type schema new SQLVarchar (128, settings_), // type name new SQLVarchar (128, settings_), // class name new SQLSmallint (vrm,settings_), // data type //@trunc3 new SQLVarchar (2000, settings_), // remarks new SQLSmallint (vrm,settings_), // base type //@G4A //@trunc3 }; fieldNullables = new int[] { columnNullable, // type catalog columnNullable, // type schema columnNoNulls, // type name columnNoNulls, // class name columnNoNulls, // data type columnNoNulls, // remarks columnNullable, // base type //@G4A }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // We only support DISTINCT in the types array. Determine // if this was passed as one of the elements. If null is // passed, that is like looking for everything, so make that // work like DISTINCT was passed. boolean distinctPassed = false; if (types == null) distinctPassed = true; else { for (int i = 0; i < types.length; ++i) if (types[i] == Types.DISTINCT) { distinctPassed = true; break; } } // Check for conditions that would result in an empty // result set. if ((! isCatalogValid (catalog)) || ((schemaPattern != null) && (schemaPattern.length () == 0)) || ((typeNamePattern != null) && (typeNamePattern.length () == 0)) || (distinctPassed == false)) rowCache = new JDSimpleRowCache (formatRow); // Otherwise, build a request and send. There is // no builtin request for UDTs in the ROI server, // so we implement this using a query on a catalog. else { // Build up the query, StringBuffer select = new StringBuffer (); select.append ("SELECT USER_DEFINED_TYPE_SCHEMA, " // @B2C + "USER_DEFINED_TYPE_NAME, " // @B2C + "SOURCE_TYPE, REMARKS"); if (isJDBC3) //@F2A { select.append (", SMALLINT (CASE SOURCE_TYPE " // @G4A + "WHEN 'BIGINT' THEN -5 WHEN 'CHAR' THEN 1 " // @G4A + "WHEN 'CHARACTER' THEN 1 WHEN 'GRAPHIC' THEN 1 " // @G4A + "WHEN 'NUMERIC' THEN 2 WHEN 'DECIMAL' THEN 3 " // @G4A + "WHEN 'INTEGER' THEN 4 WHEN 'SMALLINT' THEN 5 " // @G4A + "WHEN 'REAL' THEN 6 WHEN 'FLOAT' THEN 8 " // @G4A + "WHEN 'DOUBLE' THEN 8 WHEN 'DOUBLE PRECISION' THEN 8 " // @G4A + "WHEN 'VARCHAR' THEN 12 WHEN 'VARGRAPHIC' THEN 12 " // @G4A + "WHEN 'DATALINK' THEN 70 WHEN 'DATE' THEN 91 " // @G4A + "WHEN 'TIME' THEN 92 WHEN 'TIMESTMP' THEN 93 " // @G4A + "WHEN 'TIMESTAMP' THEN 93 WHEN 'BLOB' THEN 2004 " // @G4A + "WHEN 'CLOB' THEN 2005 WHEN 'DBCLOB' THEN 2005 " // @G4A + "ELSE NULL END)"); } select.append (" FROM QSYS2"); //@B2C @F2M select.append (getCatalogSeparator ()); select.append ("SYSTYPES " ); StringBuffer where = new StringBuffer (); if (schemaPattern != null) { JDSearchPattern searchPattern = new JDSearchPattern (schemaPattern); where.append (searchPattern.getSQLWhereClause ("USER_DEFINED_TYPE_SCHEMA")); // @B2C } if (typeNamePattern != null) { JDSearchPattern searchPattern = new JDSearchPattern (typeNamePattern); if (where.length () > 0) where.append (" AND "); where.append (searchPattern.getSQLWhereClause ("USER_DEFINED_TYPE_NAME")); // @B2C } if (where.length () > 0) { select.append (" WHERE "); //@J4c JDK 1.4 added a StringBuffer.append(StringBuffer) method. Do a toString() // here just in case we compile against 1.4 but run against 1.3. In that // case we would get 'method not found' select.append (where.toString()); } select.append (" ORDER BY USER_DEFINED_TYPE_SCHEMA, USER_DEFINED_TYPE_NAME"); // @B2C // Run the query. try { Statement statement = connection_.createStatement(); ResultSet serverResultSet = statement.executeQuery (select.toString()); JDRowCache serverRowCache = new JDSimpleRowCache (((AS400JDBCResultSet) serverResultSet).getRowCache ()); statement.close (); // Set up the maps. JDFieldMap[] maps = null; //@F2C if (!isJDBC3) //@F2A { maps = new JDFieldMap[] { new JDHardcodedFieldMap (connection_.getCatalog ()), // type catalog new JDSimpleFieldMap (1), // type schema new JDSimpleFieldMap (2), // type name new JDClassNameFieldMap (3, settings_, connection_.getVRM(), connection_.getProperties()), // class name // @B3C // @M0C new JDHardcodedFieldMap (new Integer (Types.DISTINCT)), // data type new JDHandleNullFieldMap (4, ""), // remarks // @B3C }; } else { maps = new JDFieldMap[] { new JDHardcodedFieldMap (connection_.getCatalog ()), // type catalog new JDSimpleFieldMap (1), // type schema new JDSimpleFieldMap (2), // type name new JDClassNameFieldMap (3, settings_, connection_.getVRM(), connection_.getProperties()), // class name // @B3C // @M0C new JDHardcodedFieldMap (new Integer (Types.DISTINCT)), // data type new JDHandleNullFieldMap (4, ""), // remarks // @B3C new JDSimpleFieldMap (5) // base type // @G4A }; } JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } catch (SQLException e) { // If the system does not have this table, then // force an empty result set. This just means // that UDTs are not supported (which is true // for pre-V4R4 systems). if (e.getErrorCode () == -204) rowCache = new JDSimpleRowCache (formatRow); else JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } } // Return the result set. return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "UDTs", connection_, null); //@in2 } /** Returns the URL for this database. @return The URL for this database. @exception SQLException If the connection is not open or an error occurs. **/ public String getURL () throws SQLException { connection_.checkOpen (); return connection_.getURL(); } /** Returns the current user name as known to the database. @return The current user name as known to the database. @exception SQLException If the connection is not open or an error occurs. **/ public String getUserName () throws SQLException { connection_.checkOpen (); return connection_.getUserName(); } /** Returns a description of a table's columns that are automatically updated when any value in a row is updated. @param catalog The catalog name. If null is specified, this parameter is ignored. If empty string is specified, an empty result set is returned. @param schema The schema name. If null is specified, the default SQL schema specified in the URL is used. If null is specified and a default SQL schema was not specified in the URL, the first library specified in the libraries properties file is used. If null is specified, a default SQL schema was not specified in the URL, and a library was not specified in the libraries properties file, QGPL is used. If empty string is specified, an empty result set will be returned. @param table The table name. If null or empty string is specified, an empty result set is returned. @return The ResultSet containing the description of the table's columns that are automatically updated when any value in a row is updated. @exception SQLException If the connection is not open or an error occurs. **/ public ResultSet getVersionColumns (String catalog, String schema, String table) throws SQLException { DBReplyRequestedDS reply = null; connection_.checkOpen (); int vrm = connection_.getVRM(); //@trunc3 //@mdsp SYSIBM SP Call if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE)) { CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLSPECIALCOLUMNS(?,?,?,?, ?,?,?)"); cs.setShort(1, (short) SQL_ROWVER); cs.setString(2, normalize(catalog)); cs.setString(3, normalize(schema)); cs.setString(4, normalize(table)); cs.setShort(5, (short) 0); cs.setShort(6, (short) 1); cs.setString(7, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); cs.execute(); ResultSet rs = cs.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cs.close(); //@mdrs2 return rs; //@mdrs } //-------------------------------------------------------- // Set up the result set in the format required by JDBC //-------------------------------------------------------- String[] fieldNames = {"SCOPE", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "PSEUDO_COLUMN", }; SQLData[] sqlData = { new SQLSmallint (vrm,settings_), // scope //@trunc3 new SQLVarchar (128, settings_), // column name new SQLSmallint (vrm,settings_), // data type //@trunc3 new SQLVarchar (128, settings_), // type name new SQLInteger (vrm,settings_), // column size //@trunc3 new SQLInteger (vrm,settings_), // buffer length //@trunc3 new SQLSmallint (vrm,settings_), // decimal digits //@trunc3 new SQLSmallint (vrm,settings_), // pseudo column //@trunc3 }; int[] fieldNullables = {columnNoNulls, // scope columnNoNulls, // column name columnNoNulls, // data type columnNoNulls, // type name columnNoNulls, // column size columnNoNulls, // buffer length columnNoNulls, // decimal digits columnNoNulls, // pseudo column }; JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDRowCache rowCache = null; // Creates a set of rows // that are readable one at a time. try { // Check for conditions that would result in an empty result set // Must check for null first to avoid NullPointerException if (!isCatalogValid(catalog) || // catalog is empty string // schema is not null and is empty string ((schema != null) && (schema.length()==0)) || // Table is null (table==null) || // Table is empty string (table.length()==0 )) { // Return empty result set rowCache = new JDSimpleRowCache (formatRow); } else { // parameter values are valid, build request & send // Create a request //@P0C DBReturnObjectInformationRequestDS request = null; try { request = DBDSPool.getDBReturnObjectInformationRequestDS ( DBReturnObjectInformationRequestDS.FUNCTIONID_SPECIAL_COLUMN_INFO , id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0); // Set the library name if (schema == null) { // use default SQL schema or qgpl request.setLibraryName(normalize(connection_.getDefaultSchema()), connection_.getConverter()); // @E4C } else request.setLibraryName(normalize(schema), connection_.getConverter()); // @E4C // Set the table name request.setFileName(normalize(table), connection_.getConverter()); // @E4C // Set the Field Information to Return Bitmap // Return library, table, and column request.setSpecialColumnsReturnInfoBitmap(0x1F800000); //@rchg set 8th bit for row change timestamp column information // Set the short / long file and field name indicator request.setFileShortOrLongNameIndicator(0xF0); // Long // Set columns nullable indicator to allows nullable columns request.setSpecialColumnsNullableIndicator(0xF1); //-------------------------------------------------------- // Send the request and cache all results from the system //-------------------------------------------------------- reply = connection_.sendAndReceive(request); // Check for errors - throw exception if errors were // returned int errorClass = reply.getErrorClass(); if (errorClass !=0) { int returnCode = reply.getReturnCode(); reply.returnToPool(); reply = null; throw JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } // Get the data format and result data DBDataFormat dataFormat = reply.getDataFormat(); DBData resultData = reply.getResultData(); if (resultData != null) { JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_); JDRowCache serverRowCache = new JDSimpleRowCache (new JDServerRowCache (row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE)); // Create the mapped row format that is returned in the // result set. // This does not actual move the data, it just sets up // the mapping. JDFieldMap[] maps = new JDFieldMap[8]; maps[0] = new JDHardcodedFieldMap (new Short ((short) 0)); // scope maps[1] = new JDSimpleFieldMap (1); // column name maps[2] = new JDDataTypeFieldMap (2, 3, 3, 5, 0, connection_.getVRM(), connection_.getProperties()); // @M0C // data type - converted to short //@KKB added 0 for ccsid since not given to us by host server maps[3] = new JDSimpleFieldMap (2); // type name maps[4] = new JDSimpleFieldMap (3); // column size (precision) maps[5] = new JDSimpleFieldMap(4); // buffer length maps[6] = new JDSimpleFieldMap (5); // decimal digits (scale) maps[7] = new JDHardcodedFieldMap (new Short ((short) versionColumnNotPseudo)); // Create the mapped row cache that is returned in the // result set JDMappedRow mappedRow = new JDMappedRow (formatRow, maps); rowCache = new JDMappedRowCache (mappedRow, serverRowCache); } else rowCache = new JDSimpleRowCache (formatRow); } finally { if (request != null) { request.returnToPool(); request = null; } // if (reply != null) { reply.returnToPool(); reply = null; } } } // End of else to build and send request } // End of try block catch (DBDataStreamException e) { // if (reply != null) { reply.returnToPool(); reply = null; } JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); } // Return the results return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "VersionColumns", connection_, reply); //@in2 } // JDBC 2.0 /** Indicates if visible inserts to a result set of the specified type can be detected by calling ResultSet.rowInserted(). @param resultSetType The result set type. Value values are:

  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return Always false. Inserts can not be detected by calling ResultSet.rowInserted(). @exception SQLException If the result set type is not valid. **/ public boolean insertsAreDetected (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return false; } /** Indicates if a catalog appears at the start or the end of a qualified name. @return Always true. A catalog appears at the start of a qualified name. @exception SQLException This exception is never thrown. **/ public boolean isCatalogAtStart () throws SQLException { return true; } /** Indicates if the specified catalog is valid for a query. If false is returned, any query using that catalog will be empty since the catalog does not refer to the current connection's catalog. @param catalog The catalog name. "" for no catalog or null to drop catalog from the selection criteria. @return true if catalog name is valid; false otherwise @exception SQLException This exception is never thrown. **/ private boolean isCatalogValid (String catalog) throws SQLException { if (catalog == null) return true; return(catalog.equalsIgnoreCase (connection_.getCatalog()) || (catalog.equalsIgnoreCase ("localhost"))); } /** Indicates if the database is in read-only mode. @return true if in read-only mode; false otherwise. @exception SQLException If the connection is not open or an error occurs. **/ public boolean isReadOnly () throws SQLException { connection_.checkOpen (); return connection_.isReadOnly (); } //@F3A /** Indicates if updateable LOB methods update a copy of the LOB or if updates are made directly to the LOB. True is returned if updateable lob methods update a copy of the LOB, false is returned if updates are made directly to the LOB. @return Always true. Updateable lob methods update a copy of the LOB. ResultSet.updateRow() must be called to update the LOB in the DB2 for IBM i database. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean locatorsUpdateCopy () throws SQLException { return true; } // @E4A // The database is not case-sensitive except when names are quoted with double // quotes. The host server flows are case-sensitive, so I will uppercase // everything to save the caller from having to do so. private String normalize(String mixedCaseName) { if(mixedCaseName == null) //@mdsp return null; //@mdsp if (mixedCaseName.length() > 2) { if (mixedCaseName.charAt(0) == '"') return JDUtilities.stripOutDoubleEmbededQuotes(mixedCaseName); //@PDC mixedCaseName.substring(1, mixedCaseName.length() - 1); } return mixedCaseName.toUpperCase(); } /** Indicates if concatenations between null and non-null values are null. @return Always true. Concatenations between null and non-null values are null. @exception SQLException This exception is never thrown. **/ public boolean nullPlusNonNullIsNull () throws SQLException { return true; } /** Indicates if null values are sorted at the end regardless of sort order. @return Always false. Null values are not sorted at the end regardless of sort order. @exception SQLException This exception is never thrown. **/ public boolean nullsAreSortedAtEnd () throws SQLException { return false; } /** Indicates if null values are sorted at the start regardless of sort order. @return Always false. Null values are not sorted at the start regardless of sort order. @exception SQLException This exception is never thrown. **/ public boolean nullsAreSortedAtStart () throws SQLException { return false; } /** Indicates if null values are sorted high. @return Always true. Null values are sorted high. @exception SQLException This exception is never thrown. **/ public boolean nullsAreSortedHigh () throws SQLException { return true; } /** Indicates if null values are sorted low. @return Always false. Null values are not sorted low. @exception SQLException This exception is never thrown. **/ public boolean nullsAreSortedLow () throws SQLException { return false; } // JDBC 2.0 /** Indicates if deletes made by others are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if deletes made by others are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean othersDeletesAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } // JDBC 2.0 /** Indicates if inserts made by others are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if inserts made by others are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean othersInsertsAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } // JDBC 2.0 /** Indicates if updates made by others are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if updates made by others are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean othersUpdatesAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } // JDBC 2.0 /** Indicates if a result set's own deletes are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if the result set's own deletes are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean ownDeletesAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } // JDBC 2.0 /** Indicates if a result set's own inserts are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if the result set's own inserts are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean ownInsertsAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } // JDBC 2.0 /** Indicates if a result set's own updates are visible. @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true if the result set's own updates are visible; false otherwise. @exception SQLException If the result set type is not valid. **/ public boolean ownUpdatesAreVisible (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE); } /** Indicates if the database treats mixed case, unquoted SQL identifiers as case insensitive and stores them in lowercase. @return Always false. The database does not treat mixed case, unquoted SQL identifiers as case insensitive and store them in lowercase. @exception SQLException This exception is never thrown. **/ public boolean storesLowerCaseIdentifiers () throws SQLException { return false; } /** Indicates if the database treats mixed case, quoted SQL identifiers as case insensitive and stores them in lowercase. @return Always false. The database does not treat mixed case, quoted SQL identifiers as case insensitive and store them in lowercase. @exception SQLException This exception is never thrown. */ public boolean storesLowerCaseQuotedIdentifiers () throws SQLException { return false; } /** Indicates if the database treats mixed case, unquoted SQL identifiers as case insensitive and stores them in mixed case. @return Always false. The database does not treat mixed case, unquoted SQL identifiers as case insensitive and store them in mixed case. @exception SQLException This exception is never thrown. **/ public boolean storesMixedCaseIdentifiers () throws SQLException { return false; } /** Indicates if the database treats mixed case, quoted SQL identifiers as case insensitive and stores them in mixed case. @return Always false. The database does not treat mixed case, quoted SQL identifiers as case insensitive and store them in mixed case. @exception SQLException This exception is never thrown. **/ public boolean storesMixedCaseQuotedIdentifiers () throws SQLException { // @A2C changed from false to true return false; //@pdc match other drivers } /** Indicates if the database treats mixed case, unquoted SQL identifiers as case insensitive and stores them in uppercase. @return Always true. The database does treat mixed case, unquoted SQL identifiers as case insensitive and store them in uppercase. @exception SQLException This exception is never thrown. **/ public boolean storesUpperCaseIdentifiers () throws SQLException { return true; } /** Indicates if the database treats mixed case, quoted SQL identifiers as case insensitive and stores them in uppercase. @return Always false. The database does not treat mixed case, quoted SQL identifiers as case insensitive and store them in uppercase. @exception SQLException This exception is never thrown. **/ public boolean storesUpperCaseQuotedIdentifiers () throws SQLException { return false; } /** Indicates if ALTER TABLE with ADD COLUMN is supported. @return Always true. ALTER TABLE with ADD COLUMN is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsAlterTableWithAddColumn () throws SQLException { // @A2C Changed from false to true return true; } /** Indicates if ALTER TABLE with DROP COLUMN is supported. @return Always true. ALTER TABLE with DROP COLUMN is not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsAlterTableWithDropColumn () throws SQLException { // @A2C Changed from false to true return true; } /** Indicates if the ANSI92 entry-level SQL grammar is supported. @return Always true. The ANSI92 entry-level SQL grammar is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsANSI92EntryLevelSQL () throws SQLException { // ANSI92EntryLevelSQL is supported for V4R2 and beyond // true is always returned since it is checked for compliance. return true; } /** Indicates if the ANSI92, full SQL grammar is supported. @return Always false. ANSI92, full SQL grammar is not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsANSI92FullSQL () throws SQLException { return false; } /** Indicates if the ANSI92 intermediate-level SQL grammar is supported. @return Always false. ANSI92 intermediate-level SQL grammar is not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsANSI92IntermediateSQL () throws SQLException { return false; } // JDBC 2.0 /** Indicates if the batch updates are supported. @return Always true. Batch updates are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsBatchUpdates () throws SQLException { return true; } /** Indicates if a catalog name can be used in a data manipulation statement. @return Always false. A catalog name can not be used in a data manipulation statement. @exception SQLException This exception is never thrown. **/ public boolean supportsCatalogsInDataManipulation () throws SQLException { // @A2 Changed from true to false. return false; } /** Indicates if a catalog name can be used in an index definition statement. @return Always false. A catalog name can not be used in an index definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsCatalogsInIndexDefinitions () throws SQLException { // @A2C Changed from true to false return false; } /** Indicates if a catalog name can be used in a privilege definition statement. @return Always false. A catalog name can not be used in a privilege definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsCatalogsInPrivilegeDefinitions () throws SQLException { // @A2C Changed from true to false return false; } /** Indicates if a catalog name can be used in a procedure call statement. @return Always false. A catalog name can not be used in a procedure call statement. @exception SQLException This exception is never thrown. **/ public boolean supportsCatalogsInProcedureCalls () throws SQLException { // @A2C Changed from true to false return false; } /** Indicates if a catalog name can be used in a table definition statement. @return Always false. A catalog name can not be used in a table definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsCatalogsInTableDefinitions () throws SQLException { // @A2C Changed from true to false return false; } /** Indicates if column aliasing is supported. Column aliasing means that the SQL AS clause can be used to provide names for computed columns or to provide alias names for column as required. @return Always true. Column aliasing is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsColumnAliasing () throws SQLException { return true; } /** Indicates if the CONVERT function between SQL types is supported. @return true if the CONVERT function between SQL types is supported; false otherwise. @exception SQLException This exception is never thrown. **/ public boolean supportsConvert () throws SQLException { return JDEscapeClause.supportsConvert (); } /** Indicates if CONVERT between the given SQL types is supported. @param fromType The SQL type code defined in java.sql.Types. @param toType The SQL type code defined in java.sql.Types. @return true if CONVERT between the given SQL types is supported; false otherwise. @exception SQLException This exception is never thrown. **/ public boolean supportsConvert (int fromType, int toType) throws SQLException { return JDEscapeClause.supportsConvert (fromType, toType); } /** Indicates if the ODBC Core SQL grammar is supported. @return Always true. The ODBC Core SQL grammar is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsCoreSQLGrammar () throws SQLException { return true; } /** Indicates if the correlated subqueries are supported. @return Always true. Correlated subqueries are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsCorrelatedSubqueries () throws SQLException { return true; } /** Indicates if both data definition and data manipulation statements are supported within a transaction. @return Always true. Data definition and data manipulation statements are both supported within a transaction. @exception SQLException This exception is never thrown. **/ public boolean supportsDataDefinitionAndDataManipulationTransactions () throws SQLException { return true; } /** Indicates if data manipulation statements are supported within a transaction. @return Always false. Data manipulation statements are not supported within a transaction. @exception SQLException This exception is never thrown. **/ public boolean supportsDataManipulationTransactionsOnly () throws SQLException { // @A2C Changed from true to false return false; } /** Indicates if table correlation names are supported, and if so, are they restricted to be different from the names of the tables. @return Always false. Table correlation names are not restricted to be different from the names of the tables. @exception SQLException This exception is never thrown. **/ public boolean supportsDifferentTableCorrelationNames () throws SQLException { return false; } /** Indicates if expressions in ORDER BY lists are supported. @return Always true. Expression in ORDER BY lists have been supported since V5R2. @exception SQLException This exception is never thrown. **/ public boolean supportsExpressionsInOrderBy () throws SQLException { return true; } /** Indicates if the ODBC Extended SQL grammar is supported. @return Always false. The ODBC Extended SQL grammar is not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsExtendedSQLGrammar () throws SQLException { return false; } /** Indicates if full nested outer joins are supported. @return Always false. Full nested outer joins are not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsFullOuterJoins () throws SQLException { if(connection_.getVRM() >= JDUtilities.vrm610) //@550 return true; //@550 else //@550 return false; } //@G4A /** Indicates if, after a statement is executed, auto-generated keys can be retrieved using the method Statement.getGeneratedKeys(). @return True if the user is connecting to a system running OS/400 V5R2 or IBM i, otherwise false. Auto-generated keys are supported only if connecting to a system running OS/400 V5R2 or IBM i. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean supportsGetGeneratedKeys () throws SQLException { if (connection_.getVRM() >= JDUtilities.vrm520) return true; else return false; } /** Indicates if some form of the GROUP BY clause is supported. @return Always true. Some form of GROUP BY clause is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsGroupBy () throws SQLException { return true; } /** Indicates if a GROUP BY clause can add columns not in the SELECT provided it specifies all of the columns in the SELECT. @return Always true. A GROUP BY clause can add columns not in the SELECT provided it specifies all of the columns in the SELECT. @exception SQLException This exception is never thrown. **/ public boolean supportsGroupByBeyondSelect () throws SQLException { return true; } /** Indicates if a GROUP BY clause can use columns not in the SELECT. @return Always true. A GROUP BY clause can use columns not in the SELECT. @exception SQLException This exception is never thrown. **/ public boolean supportsGroupByUnrelated () throws SQLException { return true; } /** Indicates if the SQL Integrity Enhancement Facility is supported. @return Always false. The SQL Integrity Enhancement Facility is not supported. @exception SQLException This exception is never thrown. **/ public boolean supportsIntegrityEnhancementFacility () throws SQLException { return false; } /** Indicates if the escape character in LIKE clauses is supported. @return Always true. The escape character in LIKE clauses is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsLikeEscapeClause () throws SQLException { return true; } /** Indicates if there is limited support for outer joins. @return Always true. There is limited support for outer joins. @exception SQLException This exception is never thrown. **/ public boolean supportsLimitedOuterJoins () throws SQLException { return true; } /** Indicates if the ODBC Minimum SQL grammar is supported. @return Always true. The ODBC Minimum SQL grammar is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsMinimumSQLGrammar () throws SQLException { return true; } /** Indicates if the database treats mixed case, unquoted SQL identifiers as case sensitive and stores them in mixed case. @return Always false. The database does not treat mixed case, unquoted SQL identifiers as case sensitive and as a result store them in mixed case. @exception SQLException This exception is never thrown. **/ public boolean supportsMixedCaseIdentifiers () throws SQLException { return false; } /** Indicates if the database treats mixed case, quoted SQL identifiers as case sensitive and as a result stores them in mixed case. @return Always true. The database does treat mixed case, quoted SQL identifiers as case sensitive and stores them in mixed case. @exception SQLException This exception is never thrown. **/ public boolean supportsMixedCaseQuotedIdentifiers () throws SQLException { return true; } //@G4A /** Indicates if multiple result sets can be returned from a CallableStatement simultaneously. @return Always false. Multiple open result sets from a single execute are not supported by the Toolbox driver. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean supportsMultipleOpenResults () throws SQLException { return false; } /** Indicates if multiple result sets from a single execute are supported. @return Always true. Multiple result sets from a single execute are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsMultipleResultSets () throws SQLException { return true; } /** Indicates if multiple transactions can be open at once (on different connections). @return Always true. Multiple transactions can be open at once on different connections. @exception SQLException This exception is never thrown. **/ public boolean supportsMultipleTransactions () throws SQLException { return true; } //@G4A /** Indicates if using parameter names to specify parameters on callable statements are supported. @return Always true. An application can use parameter names to specify parameters on callable statements. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean supportsNamedParameters () throws SQLException { return true; } /** Indicates if columns can be defined as non-nullable. @return Always true. Columns can be defined as non-nullable. @exception SQLException This exception is never thrown. **/ public boolean supportsNonNullableColumns () throws SQLException { return true; } /** Indicates if cursors can remain open across commits. @return Always true. Cursors can remain open across commits. @exception SQLException This exception is never thrown. **/ public boolean supportsOpenCursorsAcrossCommit () throws SQLException { return true; } /** Indicates if cursors can remain open across rollback. @return Always true. Cursors can remain open across rollback. @exception SQLException This exception is never thrown. **/ public boolean supportsOpenCursorsAcrossRollback () throws SQLException { return true; } /** Indicates if statements can remain open across commits. @return Always true. Statements can remain open across commits. @exception SQLException This exception is never thrown. **/ public boolean supportsOpenStatementsAcrossCommit () throws SQLException { return true; } /** Indicates if statements can remain open across rollback. @return Always true. Statements can remain open across rollback. @exception SQLException This exception is never thrown. **/ public boolean supportsOpenStatementsAcrossRollback () throws SQLException { return true; } /** Indicates if an ORDER BY clause can use columns not in the SELECT. @return Always false. ORDER BY cannot use columns not in the SELECT. @exception SQLException This exception is never thrown. **/ public boolean supportsOrderByUnrelated () throws SQLException { return false; } /** Indicates if some form of outer join is supported. @return Always true. Some form of outer join is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsOuterJoins () throws SQLException { return true; } /** Indicates if positioned DELETE is supported. @return Always true. Positioned DELETE is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsPositionedDelete () throws SQLException { return true; } /** Indicates if positioned UPDATE is supported. @return Always true. Positioned UPDATE is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsPositionedUpdate () throws SQLException { return true; } // JDBC 2.0 // @C0C /** Indicates if the specified result set concurrency is supported for the specified result set type.

This chart describes the combinations of result set concurrency and type that this driver supports:


CONCUR_READ_ONLYCONCUR_UPDATABLE
TYPE_FORWARD_ONLYYesYes
TYPE_SCROLL_INSENSITIVEYesNo
TYPE_SCROLL_SENSITIVEYesYes

@param resultSetType The result set type. Valid values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@param resultSetConcurrency The result set concurrency. Valid values are:
  • ResultSet.CONCUR_READ_ONLY
  • ResultSet.CONCUR_UPDATABLE
@return true if the specified result set concurrency is supported for the specified result set type; false otherwise. @exception SQLException If the result set type or result set concurrency is not valid. **/ // // Implementation note: // // The unsupported combinations are dictated by the DB2 // cursor support. // public boolean supportsResultSetConcurrency (int resultSetType, int resultSetConcurrency) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); // Validate the result set concurrency. if ((resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) && (resultSetConcurrency != ResultSet.CONCUR_UPDATABLE)) JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID); // Cases that we don't support. //@K2D if (((resultSetConcurrency == ResultSet.CONCUR_READ_ONLY) //@K2D && (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE)) //@K2D || ((resultSetConcurrency == ResultSet.CONCUR_UPDATABLE) //@K2D && (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE))) if((resultSetConcurrency == ResultSet.CONCUR_UPDATABLE) //@K2A && (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE)) //@K2A return false; // We support all other cases. return true; } //@G4A /** Indicates if a type of result set holdability is supported. The two types are ResultSet.HOLD_CURSORS_OVER_COMMIT and ResultSet.CLOSE_CURSORS_AT_COMMIT. @return True if the user is connecting to a system running OS/400 V5R2 or IBM i, otherwise false. Both types of result set holidability are supported if connecting to OS/400 V5R2 or IBM i. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean supportsResultSetHoldability (int resultSetHoldability) throws SQLException { if (connection_.getVRM() >= JDUtilities.vrm520) return true; else return false; } //@G4A /** Indicates if savepoints are supported. @return True if the user is connecting to a system running OS/400 V5R2 or IBM i, otherwise false. Savepoints are supported only if connecting to OS/400 V5R2 or IBM i. @exception SQLException This exception is never thrown. @since Modification 5 **/ public boolean supportsSavepoints () throws SQLException { // Note we check only the system level. We don't need to // check JDBC/JDK level because if running prior to JDBC 3.0 // the app cannot call this method (it does not exist // in the interface). if (connection_.getVRM() >= JDUtilities.vrm520) return true; else return false; } // JDBC 2.0 /** Indicates if the specified result set type is supported. @param resultSetType The result set type. Valid values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return true for ResultSet.TYPE_FORWARD_ONLY ResultSet.TYPE_SCROLL_SENSITIVE. and ResultSet.TYPE_SCROLL_INSENSITIVE. @exception SQLException If the result set type is not valid. **/ public boolean supportsResultSetType (int resultSetType) throws SQLException { switch(resultSetType) { case ResultSet.TYPE_FORWARD_ONLY: case ResultSet.TYPE_SCROLL_SENSITIVE: case ResultSet.TYPE_SCROLL_INSENSITIVE: return true; default: JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID); return false; } } /** Indicates if a schema name can be used in a data manipulation statement. @return Always true. A schema name can be used in a data manipulation statement. @exception SQLException This exception is never thrown. **/ public boolean supportsSchemasInDataManipulation () throws SQLException { return true; } /** Indicates if a schema name can be used in an index definition statement. @return Always true. A schema name can be used in an index definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsSchemasInIndexDefinitions () throws SQLException { return true; } /** Indicates if a schema name be can used in a privilege definition statement. @return Always true. A schema name can be used in a privilege definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsSchemasInPrivilegeDefinitions () throws SQLException { return true; } /** Indicates if a schema name be can used in a procedure call statement. @return Always true. A schema name can be used in a procedure call statement. @exception SQLException This exception is never thrown. **/ public boolean supportsSchemasInProcedureCalls () throws SQLException { return true; } /** Indicates if a schema name can be used in a table definition statement. @return Always true. A schema name can be used in a table definition statement. @exception SQLException This exception is never thrown. **/ public boolean supportsSchemasInTableDefinitions () throws SQLException { return true; } /** Indicates if SELECT for UPDATE is supported. @return Always true. SELECT for UPDATE is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsSelectForUpdate () throws SQLException { return true; } //@B0A - We don't support this directly. Use package caching instead. /** * Indicates if statement pooling is supported. * @return Always false. Statement pooling is not supported at this time. **/ public boolean supportsStatementPooling() { return false; } /** Indicates if stored procedure calls using the stored procedure escape syntax are supported. @return Always true. Stored procedure calls using the stored procedure escape syntax are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsStoredProcedures () throws SQLException { return true; } /** Indicates if subqueries in comparisons are supported. @return Always true. Subqueries in comparisons are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsSubqueriesInComparisons () throws SQLException { return true; } /** Indicates if subqueries in EXISTS expressions are supported. @return Always true. Subqueries in EXISTS expressions are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsSubqueriesInExists () throws SQLException { return true; } /** Indicates if subqueries in IN expressions are supported. @return Always true. Subqueries in IN expressions are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsSubqueriesInIns () throws SQLException { return true; } /** Indicates if subqueries in quantified expressions are supported. @return Always true. Subqueries in quantified expressions are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsSubqueriesInQuantifieds () throws SQLException { return true; } /** Indicates if table correlation names are supported. @return Always true. Table correlation names are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsTableCorrelationNames () throws SQLException { return true; } /** Indicates if the database supports the given transaction isolation level. @param transactionIsolationLevel One of the Connection.TRANSACTION_* values. @return Always true. All transaction isolation levels are supported. @exception SQLException If the transaction isolation level is not valid. **/ public boolean supportsTransactionIsolationLevel (int transactionIsolationLevel) throws SQLException { // Validate the transaction isolation level. if ((transactionIsolationLevel != Connection.TRANSACTION_NONE) && (transactionIsolationLevel != Connection.TRANSACTION_READ_UNCOMMITTED) && (transactionIsolationLevel != Connection.TRANSACTION_READ_COMMITTED) && (transactionIsolationLevel != Connection.TRANSACTION_REPEATABLE_READ) && (transactionIsolationLevel != Connection.TRANSACTION_SERIALIZABLE)) JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID); if(transactionIsolationLevel == Connection.TRANSACTION_NONE) { return false; // we have determined that we do not support JDBC's idea of TRANSACTION_NONE } else { return true; } } /** Indicates if transactions are supported. @return Always true. Transactions are supported. @exception SQLException This exception is never thrown. **/ public boolean supportsTransactions () throws SQLException { return true; } /** Indicates if SQL UNION is supported. @return Always true. SQL UNION is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsUnion () throws SQLException { return true; } /** Indicates if SQL UNION ALL is supported. @return Always true. SQL UNION ALL is supported. @exception SQLException This exception is never thrown. **/ public boolean supportsUnionAll () throws SQLException { return true; } /** Returns the name of the catalog. @return The name of the catalog. **/ public String toString () { try { return connection_.getCatalog(); } catch (SQLException e) { return super.toString (); } } // JDBC 2.0 /** Indicates if visible updates to a result set of the specified type can be detected by calling ResultSet.rowUpdated(). @param resultSetType The result set type. Value values are:
  • ResultSet.TYPE_FORWARD_ONLY
  • ResultSet.TYPE_SCROLL_INSENSITIVE
  • ResultSet.TYPE_SCROLL_SENSITIVE
@return Always false. Updates can not be detected by calling ResultSet.rowUpdated(). @exception SQLException If the result set type is not valid. **/ public boolean updatesAreDetected (int resultSetType) throws SQLException { // Validate the result set type. supportsResultSetType (resultSetType); return false; } /** Indicates if the database uses a file for each table. @return Always false. The database does not use a file for each table. @exception SQLException This exception is never thrown. **/ public boolean usesLocalFilePerTable () throws SQLException { return false; } /** Indicates if the database stores tables in a local file. @return Always false. The database does not store tables in a local file. @exception SQLException This exception is never thrown. **/ public boolean usesLocalFiles () throws SQLException { return false; } //@pda jdbc40 protected String[] getValidWrappedList() { return new String[] { "com.ibm.as400.access.AS400JDBCDatabaseMetaData", "java.sql.DatabaseMetaData" }; } //@PDA jdbc40 /** * Retrieves whether a SQLException thrown while autoCommit is true indicates * that all open ResultSets are closed, even ones that are holdable. When a SQLException occurs while * autocommit is true, it is vendor specific whether the JDBC driver responds with a commit operation, a * rollback operation, or by doing neither a commit nor a rollback. A potential result of this difference * is in whether or not holdable ResultSets are closed. * * * @return true if so; false otherwise * @exception SQLException if a database access error occurs */ public boolean autoCommitFailureClosesAllResultSets() throws SQLException { return false; //toolbox returns false based on current behavoir } //@PDA jdbc40 /** * Retrieves a list of the client info properties * that the driver supports. The result set contains the following columns *

*

    *
  1. NAME String => The name of the client info property
    *
  2. MAX_LEN int => The maximum length of the value for the property
    *
  3. DEFAULT_VALUE String => The default value of the property
    *
  4. DESCRIPTION String => A description of the property. This will typically * contain information as to where this property is * stored in the database. *
*

* The ResultSet is sorted by the NAME column in ascending order *

* @return A ResultSet object; each row is a supported client info * property *

* @exception SQLException if a database access error occurs *

*/ public ResultSet getClientInfoProperties() throws SQLException { // Set up the result set. int vrm = connection_.getVRM(); //@trunc3 String[] fieldNames = { "NAME", "MAX_LEN", "DEFAULT_VALUE", "DESCRIPTION" }; SQLData[] sqlData = { new SQLVarchar(32, settings_), new SQLInteger(vrm,settings_), new SQLVarchar(32, settings_), new SQLVarchar(1024, settings_) }; //trunc3 int[] fieldNullables = {columnNoNulls, columnNoNulls, columnNoNulls, columnNoNulls}; // table types can not be null Object[][] data = { { "ApplicationName", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_APPLICATIONNAME",null) }, { "ClientUser", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTUSER",null)}, { "ClientHostname", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTHOSTNAME",null)}, { "ClientAccounting", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTACCOUNTING",null)}, { "ClientProgramID", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTPROGRAMID",null)}}; //@pdc programID JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables); JDSimpleRowCache rowCache = new JDSimpleRowCache(formatRow, data); return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Client Info", connection_, null); //@in2 } //@PDA jdbc40 //JDBC40DOC /** //JDBC40DOC * Indicates whether or not this data source supports the SQL ROWID type, //JDBC40DOC * and if so the lifetime for which a RowId object remains valid. //JDBC40DOC *

//JDBC40DOC * The returned int values have the following relationship: //JDBC40DOC *

  //JDBC40DOC      *     ROWID_UNSUPPORTED < ROWID_VALID_OTHER < ROWID_VALID_TRANSACTION
  //JDBC40DOC      *         < ROWID_VALID_SESSION < ROWID_VALID_FOREVER
  //JDBC40DOC      * 
//JDBC40DOC * so conditional logic such as //JDBC40DOC *
  //JDBC40DOC      *     if (metadata.getRowIdLifetime() > DatabaseMetaData.ROWID_VALID_TRANSACTION)
  //JDBC40DOC      * 
//JDBC40DOC * can be used. Valid Forever means valid across all Sessions, and valid for //JDBC40DOC * a Session means valid across all its contained Transactions. //JDBC40DOC * //JDBC40DOC * @throws SQLException if a database access error occurs //JDBC40DOC */ /* ifdef JDBC40 public RowIdLifetime getRowIdLifetime() throws SQLException { return RowIdLifetime.ROWID_VALID_FOREVER; //toolbox rowid is forever } endif */ //@PDA jdbc40 /** * Retrieves the schema names available in this database. The results * are ordered by schema name. * *

The schema column is: *

    *
  1. TABLE_SCHEM String => schema name *
  2. TABLE_CATALOG String => catalog name (may be null) *
* * * @param catalog a catalog name; must match the catalog name as it is stored * in the database;"" retrieves those without a catalog; null means catalog * name should not be used to narrow down the search. * @param schemaPattern a schema name; must match the schema name as it is * stored in the database; null means * schema name should not be used to narrow down the search. * @return a ResultSet object in which each row is a * schema decription * @exception SQLException if a database access error occurs * @see #getSearchStringEscape */ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { connection_.checkOpen(); CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLTABLES (?, ?, ?, ?, ?)"); cstmt.setString(1, normalize(catalog)); cstmt.setString(2, normalize(schemaPattern)); cstmt.setString(3, "%"); //@mdsp cstmt.setString(4, "%"); //@mdsp cstmt.setObject(5, "DATATYPE='JDBC';GETSCHEMAS=2;CURSORHOLD=1"); cstmt.execute(); //@mdrs ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } //@PDA jdbc40 /** * Retrieves whether this database supports invoking user-defined or vendor functions * using the stored procedure escape syntax. * * @return true if so; false otherwise * @exception SQLException if a database access error occurs */ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { // toolbox does not support this return false; } //@PDA jdbc40 /** * Retrieves a description of the user functions available in the given * catalog. *

* Only system and user function descriptions matching the schema and * function name criteria are returned. They are ordered by * FUNCTION_CAT, FUNCTION_SCHEM, * FUNCTION_NAME and * SPECIFIC_ NAME. * *

Each function description has the the following columns: *

    *
  1. FUNCTION_CAT String => function catalog (may be null) *
  2. FUNCTION_SCHEM String => function schema (may be null) *
  3. FUNCTION_NAME String => function name. This is the name * used to invoke the function *
  4. REMARKS String => explanatory comment on the function *
  5. FUNCTION_TYPE short => kind of function: *
      *
    • functionResultUnknown - Cannot determine if a return value * or table will be returned *
    • functionNoTable- Does not return a table *
    • functionReturnsTable - Returns a table *
    *
  6. SPECIFIC_NAME String => the name which uniquely identifies * this function within its schema. This is a user specified, or DBMS * generated, name that may be different then the FUNCTION_NAME * for example with overload functions *
*

* A user may not have permissions to execute any of the functions that are * returned by getFunctions * * @param catalog a catalog name; must match the catalog name as it * is stored in the database; "" retrieves those without a catalog; * null means that the catalog name should not be used to narrow * the search * @param schemaPattern a schema name pattern; must match the schema name * as it is stored in the database; "" retrieves those without a schema; * null means that the schema name should not be used to narrow * the search * @param functionNamePattern a function name pattern; must match the * function name as it is stored in the database * @return ResultSet - each row is a function description * @exception SQLException if a database access error occurs * @see #getSearchStringEscape */ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { connection_.checkOpen(); // @A3 Not sure why this was not supported, since the stored procedure exists on V5R4 // if(connection_.getVRM() < JDUtilities.vrm610) //@pda HSTSRVR support not PTFing support to v5r4 // { // JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); // return null; //} /* SYSIBM.SQLFunctions( CatalogName varchar(128), SchemaName varchar(128), FunctionName varchar(128), Options varchar(4000)) */ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLFUNCTIONS ( ?, ?, ?, ?)"); cstmt.setString(1, normalize(catalog)); cstmt.setString(2, normalize(schemaPattern)); cstmt.setString(3, normalize(functionNamePattern)); cstmt.setObject(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp cstmt.execute(); //@mdrs ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } //@pda jdbc40 /** * Retrieves a description of the given catalog's system or user * function parameters and return type. * *

Only descriptions matching the schema, function and * parameter name criteria are returned. They are ordered by * FUNCTION_CAT, FUNCTION_SCHEM, * FUNCTION_NAME and * SPECIFIC_ 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. * *

Each row in the ResultSet * is a parameter description, column description or * return type description with the following fields: *

    *
  1. FUNCTION_CAT String => function catalog (may be null) *
  2. FUNCTION_SCHEM String => function schema (may be null) *
  3. FUNCTION_NAME String => function name. This is the name * used to invoke the function *
  4. COLUMN_NAME String => column/parameter name *
  5. COLUMN_TYPE Short => kind of column/parameter: *
      *
    • functionColumnUnknown - nobody knows *
    • functionColumnIn - IN parameter *
    • functionColumnInOut - INOUT parameter *
    • functionColumnOut - OUT parameter *
    • functionColumnReturn - function return value *
    • functionColumnResult - Indicates that the parameter or column * is a column in the ResultSet *
    *
  6. DATA_TYPE int => SQL type from java.sql.Types *
  7. TYPE_NAME String => SQL type name, for a UDT type the * type name is fully qualified *
  8. PRECISION int => precision *
  9. LENGTH int => length in bytes of data *
  10. SCALE short => scale - null is returned for data types where * SCALE is not applicable. *
  11. RADIX short => radix *
  12. NULLABLE short => can it contain NULL. *
      *
    • functionNoNulls - does not allow NULL values *
    • functionNullable - allows NULL values *
    • functionNullableUnknown - nullability unknown *
    *
  13. REMARKS String => comment describing column/parameter *
  14. CHAR_OCTET_LENGTH int => the maximum length of binary * and character based parameters or columns. For any other datatype the returned value * is a NULL *
  15. ORDINAL_POSITION int => the ordinal position, starting * from 1, for the input and output parameters. A value of 0 * is returned if this row describes the function's return value. * For result set columns, it is the * ordinal position of the column in the result set starting from 1. *
  16. IS_NULLABLE String => ISO rules are used to determine * the nullability for a parameter or column. *
      *
    • YES --- if the parameter or column can include NULLs *
    • NO --- if the parameter or column cannot include NULLs *
    • empty string --- if the nullability for the * parameter or column is unknown *
    *
  17. SPECIFIC_NAME String => the name which uniquely identifies * this function within its schema. This is a user specified, or DBMS * generated, name that may be different then the FUNCTION_NAME * for example with overload functions *
* *

The PRECISION column represents the specified column size for the given * parameter or column. * For numeric data, this is the maximum precision. For character data, this is the length in characters. * For datetime datatypes, this is the length in characters of the String representation (assuming the * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype, * this is the length in bytes. Null is returned for data types where the * column size is not applicable. * @param catalog a catalog name; must match the catalog name as it * is stored in the database; "" retrieves those without a catalog; * null means that the catalog name should not be used to narrow * the search * @param schemaPattern a schema name pattern; must match the schema name * as it is stored in the database; "" retrieves those without a schema; * null means that the schema name should not be used to narrow * the search * @param functionNamePattern a procedure name pattern; must match the * function name as it is stored in the database * @param columnNamePattern a parameter name pattern; must match the * parameter or column name as it is stored in the database * @return ResultSet - each row describes a * user function parameter, column or return type * * @exception SQLException if a database access error occurs * @see #getSearchStringEscape */ public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { //@PDA add support to call stored procedure connection_.checkOpen(); //@A3D Allow this to occur to V5R4 // if(connection_.getVRM() < JDUtilities.vrm610) //@pda HSTSRVR support not PTFing support to v5r4 // { // JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); // return null; // } /* SQLFunctionCols( CatalogName varchar(128), SchemaName varchar(128), FuncName varchar(128), ParamName varchar(128), Options varchar(4000)) */ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLFUNCTIONCOLS ( ?, ?, ?, ?, ?)"); cstmt.setString(1, normalize(catalog)); cstmt.setString(2, normalize(schemaPattern)); cstmt.setString(3, normalize(functionNamePattern)); cstmt.setString(4, normalize(columnNamePattern)); /* ifdef JDBC40 cstmt.setObject(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp //@ver endif */ /* ifndef JDBC40 */ cstmt.setObject(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp /* endif */ cstmt.execute();//@mdrs ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } // JDBC 4.1 /** * Retrieves whether a generated key will always be returned if the column name(s) or index(es) * specified for the auto generated key column(s) are valid and the statement succeeds. * @return true if so; false otherwise * @exception SQLException - if a database access error occurs */ public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } // JDBC 4.1 /** * Retrieves a description of the pseudo or hidden columns available in a given table within the specified * catalog and schema. Pseudo or hidden columns may not always be stored within a table and are not * visible in a ResultSet unless they are specified in the query's outermost SELECT list. Pseudo or hidden * columns may not necessarily be able to be modified. If there are no pseudo or hidden columns, an empty * ResultSet is returned. *

Only column descriptions matching the catalog, schema, table and column name criteria are returned. * They are ordered by TABLE_CAT,TABLE_SCHEM, TABLE_NAME and COLUMN_NAME. *

Each column description has the following columns: *

    *
  1. TABLE_CAT String => table catalog (may be null) *
  2. TABLE_SCHEM String => table schema (may be null) *
  3. TABLE_NAME String => table name *
  4. COLUMN_NAME String => column name *
  5. DATA_TYPE int => SQL type from java.sql.Types *
  6. COLUMN_SIZE int => column size. *
  7. DECIMAL_DIGITS int => the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable. *
  8. NUM_PREC_RADIX int => Radix (typically either 10 or 2) *
  9. COLUMN_USAGE String => The allowed usage for the column. The value returned will correspond to the enum name returned by PseudoColumnUsage.name() *
  10. REMARKS String => comment describing column (may be null) *
  11. CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column *
  12. IS_NULLABLE String => ISO rules are used to determine the nullability for a column. *
      *
    • YES --- if the column can include NULLs *
    • NO --- if the column cannot include NULLs *
    • empty string --- if the nullability for the column is unknown *
    *
*

The COLUMN_SIZE column specifies the column size for the given column. For numeric data, this is the * maximum precision. For character data, this is the length in characters. For datetime datatypes, * this is the length in characters of the String representation (assuming the maximum allowed precision of the * fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype, * this is the length in bytes. Null is returned for data types where the column size is not applicable. * * @param catalog - a catalog name; must match the catalog name as it is stored in the database; * "" retrieves those without a catalog; null means that the catalog name should not be used to narrow the search * @param schemaPattern - a schema name pattern; must match the schema name as it is stored in the database; * "" retrieves those without a schema; null means that the schema name should not be used to narrow the search * @param tableNamePattern - a table name pattern; must match the table name as it is stored in the database * @param columnNamePattern - a column name pattern; must match the column name as it is stored in the database * @return ResultSet - each row is a column description * @exception SQLException - if a database access error occurs //JDBC40DOC * @see java.sql.PseudoColumnUsage */ public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { connection_.checkOpen(); CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLPSEUDOCOLUMNS ( ?, ?, ?, ?, ?)"); cstmt.setString(1, normalize(catalog)); cstmt.setString(2, normalize(schemaPattern)); cstmt.setString(3, normalize(tableNamePattern)); cstmt.setString(4, normalize(columnNamePattern)); /* ifdef JDBC40 cstmt.setObject(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp //@ver endif */ /* ifndef JDBC40 */ cstmt.setObject(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp /* endif */ cstmt.execute();//@mdrs ResultSet rs = cstmt.getResultSet(); //@mdrs if(rs != null) //@mdrs ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs else cstmt.close(); //@mdrs2 return rs; //@mdrs } /** * Retrieves the maximum number of bytes this database allows for the logical size * for a LOB. * For IBM i, this will return 2147483647, which is the maximum number of bytes * in a DBCLOB. * @return the maximum number of bytes allowed; a result of zero means that there is no limit or the limit is not known * @exception SQLException - if a database access error occurs */ public long getMaxLogicalLobSize() throws SQLException { return 2147483647; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy