PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jtopen-7.8/src/com/ibm/as400/access/AS400JDBCDatabaseMetaData.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1100 lines | 533 code | 155 blank | 412 comment | 69 complexity | d6606f4050bb8a3a7d309f2d9ff853a0 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // JTOpen (IBM Toolbox for Java - OSS version)
  4. //
  5. // Filename: AS400JDBCDatabaseMetaData.java
  6. //
  7. // The source code contained herein is licensed under the IBM Public License
  8. // Version 1.0, which has been approved by the Open Source Initiative.
  9. // Copyright (C) 1997-2010 International Business Machines Corporation and
  10. // others. All rights reserved.
  11. //
  12. ///////////////////////////////////////////////////////////////////////////////
  13. package com.ibm.as400.access;
  14. import java.sql.CallableStatement;
  15. import java.sql.Connection;
  16. import java.sql.DatabaseMetaData;
  17. import java.sql.ResultSet;
  18. /* ifdef JDBC40 */
  19. import java.sql.RowIdLifetime;
  20. /* endif */
  21. import java.sql.SQLException;
  22. import java.sql.Statement;
  23. import java.sql.Types;
  24. import java.util.Vector; // @D0A
  25. // @E4C
  26. /**
  27. The AS400JDBCDatabaseMetaData class provides information
  28. about the database as a whole.
  29. <p>Some of the methods in this class take arguments that are
  30. pattern strings. Such arguments are suffixed with "Pattern".
  31. Within a pattern string, "%" means match any substring of zero
  32. or more characters, and "_" means match exactly one character.
  33. Only entries matching the pattern string are returned.
  34. <p>For example, if the schemaPattern argument for getTables()
  35. is "H%WO_LD", then the following schemas might match
  36. the pattern, provided they exist on the system:
  37. <pre>
  38. HELLOWORLD
  39. HIWORLD
  40. HWORLD
  41. HELLOWOULD
  42. HIWOULD
  43. </pre>
  44. <p>Many of the methods here return lists of information in
  45. result sets. You can use the normal ResultSet methods to
  46. retrieve data from these result sets. The format of the
  47. result sets are described in the JDBC interface specification.
  48. <p>Schema and table names that are passed as input to methods
  49. in this class are implicitly uppercased unless enclosed in
  50. double-quotes.
  51. **/
  52. //-----------------------------------------------------------
  53. // Using nulls and empty strings for catalog functions
  54. //
  55. // When the parameter is NOT search pattern capable and:
  56. // null is specified for:
  57. // catalog (system) - parameter is ignored
  58. // schema (library) - use default SQL schema
  59. // The default SQL schema can be
  60. // set in the URL. If not
  61. // specified in URL, the first
  62. // library specified in the library
  63. // properties is used as the
  64. // default SQL schema.
  65. // If no default SQL schema exists,
  66. // QGPL is used.
  67. // table (file) - empty result set is returned
  68. // column (field) - empty result set is returned
  69. // empty string is specified for:
  70. // catalog (system) - empty result set is returned
  71. // schema (library) - empty result set is returned
  72. // table (file) - empty result set is returned
  73. // column (field) - empty result set is returned
  74. //
  75. //
  76. // When the parameter is search pattern capable and:
  77. // null is specified for:
  78. // schemaPattern (library) - no value sent to system.
  79. // System default of
  80. // *USRLIBL is used.
  81. // tablePattern (file) - no value sent to system
  82. // system default of *ALL used
  83. // empty string is specified for:
  84. // schemaPattern (library) - empty result set is returned
  85. // tablePattern (file) - empty result set is returned
  86. //
  87. //
  88. //----------------------------------------------------------
  89. public class AS400JDBCDatabaseMetaData
  90. /* ifdef JDBC40 */
  91. extends ToolboxWrapper
  92. /* endif */
  93. implements DatabaseMetaData
  94. {
  95. static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
  96. //New constants for JDBC 3.0.
  97. public static final int sqlStateXOpen = 1;
  98. public static final int sqlStateSQL99 = 2;
  99. // Private data.
  100. private AS400JDBCConnection connection_;
  101. private int id_;
  102. private SQLConversionSettings settings_;
  103. //@mdsp misc constants for sysibm stored procedures
  104. final static int SQL_NO_NULLS = 0; //@mdsp
  105. final static int SQL_NULLABLE = 1; //@mdsp
  106. final static int SQL_NULLABLE_UNKNOWN = 2; //@mdsp
  107. final static int SQL_BEST_ROWID = 1; //@mdsp
  108. final static int SQL_ROWVER = 2; //@mdsp
  109. static final String EMPTY_STRING = ""; //@mdsp
  110. static final String MATCH_ALL = "%"; //@mdsp
  111. private static final String VIEW = "VIEW"; //@mdsp
  112. private static final String TABLE = "TABLE"; //@mdsp
  113. private static final String SYSTEM_TABLE = "SYSTEM TABLE"; //@mdsp
  114. private static final String ALIAS = "ALIAS"; //@mdsp
  115. private static final String MQT = "MATERIALIZED QUERY TABLE"; //@mdsp
  116. private static final String SYNONYM = "SYNONYM"; //@mdsp
  117. private static final String FAKE_VALUE = "QCUJOFAKE"; //@mdsp
  118. private static final int SQL_ALL_TYPES = 0; //@mdsp
  119. // the DB2 SQL reference says this should be 2147483647 but we return 1 less to allow for NOT NULL columns
  120. static final int MAX_LOB_LENGTH = 2147483646; //@xml3
  121. static int javaVersion = 0;
  122. static {
  123. String javaVersionString = System.getProperty("java.version");
  124. if (javaVersionString != null) {
  125. int dotIndex = javaVersionString.indexOf('.');
  126. if (dotIndex > 0) {
  127. int secondDotIndex = javaVersionString.indexOf('.', dotIndex+1);
  128. if (secondDotIndex > 0) {
  129. String firstDigit = javaVersionString.substring(0,dotIndex);
  130. String secondDigit = javaVersionString.substring(dotIndex+1, secondDotIndex);
  131. javaVersion = Integer.parseInt(firstDigit)*10 + Integer.parseInt(secondDigit);
  132. }
  133. } else {
  134. // Android return 0. Set as version 4. @G3A
  135. if ("0".equals(javaVersionString)) {
  136. javaVersion = 4;
  137. }
  138. }
  139. }
  140. }
  141. /**
  142. Constructs an AS400JDBCDatabaseMetaData object.
  143. @param connection The connection to the system.
  144. @param id The ID the caller has assigned to this
  145. AS400JDBCDatabaseMetaData.
  146. **/
  147. AS400JDBCDatabaseMetaData (AS400JDBCConnection connection, int id)
  148. throws SQLException
  149. {
  150. connection_ = connection;
  151. settings_ = new SQLConversionSettings (connection);
  152. id_ = id;
  153. }
  154. /**
  155. Indicates if all of the procedures returned by getProcedures() can be
  156. called by the current user.
  157. @return Always false. This driver cannot determine if all of the procedures
  158. can be called by the current user.
  159. @exception SQLException This exception is never thrown.
  160. **/
  161. public boolean allProceduresAreCallable ()
  162. throws SQLException
  163. {
  164. return false;
  165. }
  166. /**
  167. Indicates if all of the tables returned by getTables() can be
  168. SELECTed by the current user.
  169. @return Always false. This driver cannot determine if all of the tables
  170. returned by getTables() can be selected by the current user.
  171. @exception SQLException This exception is never thrown.
  172. **/
  173. public boolean allTablesAreSelectable ()
  174. throws SQLException
  175. {
  176. return false;
  177. }
  178. /**
  179. Indicates if a data definition statement within a transaction
  180. can force the transaction to commit.
  181. @return Always false. A data definition statement within a transaction
  182. does not force the transaction to commit.
  183. @exception SQLException This exception is never thrown.
  184. **/
  185. public boolean dataDefinitionCausesTransactionCommit ()
  186. throws SQLException
  187. {
  188. return false;
  189. }
  190. /**
  191. Indicates if a data definition statement within a transaction is
  192. ignored.
  193. @return Always false. A data definition statement within a
  194. transaction is not ignored.
  195. @exception SQLException This exception is never thrown.
  196. **/
  197. public boolean dataDefinitionIgnoredInTransactions ()
  198. throws SQLException
  199. {
  200. return false;
  201. }
  202. // JDBC 2.0
  203. /**
  204. Indicates if visible deletes to a result set of the specified type
  205. can be detected by calling ResultSet.rowDeleted(). If visible
  206. deletes cannot be detected, then rows are removed from the
  207. result set as they are deleted.
  208. @param resultSetType The result set type. Value values are:
  209. <ul>
  210. <li>ResultSet.TYPE_FORWARD_ONLY
  211. <li>ResultSet.TYPE_SCROLL_INSENSITIVE
  212. <li>ResultSet.TYPE_SCROLL_SENSITIVE
  213. </ul>
  214. @return Always false. Deletes can not be detected
  215. by calling ResultSet.rowDeleted().
  216. @exception SQLException If the result set type is not valid.
  217. **/
  218. public boolean deletesAreDetected (int resultSetType)
  219. throws SQLException
  220. {
  221. // Validate the result set type.
  222. supportsResultSetType (resultSetType);
  223. return false;
  224. }
  225. /**
  226. Indicates if getMaxRowSize() includes blobs when computing the
  227. maximum length of a single row.
  228. @return Always true. getMaxRowSize() does include blobs when
  229. computing the maximum length of a single row.
  230. @exception SQLException This exception is never thrown.
  231. **/
  232. public boolean doesMaxRowSizeIncludeBlobs ()
  233. throws SQLException
  234. {
  235. return true;
  236. }
  237. //@G4A
  238. /**
  239. Returns a ResultSet containing a description of type attributes available in a
  240. specified catalog.
  241. This method only applies to the attributes of a
  242. structured type. Distinct types are stored in the datatypes
  243. catalog, not the attributes catalog. Since DB2 for IBM i does not support
  244. structured types at this time, an empty ResultSet will always be returned
  245. for calls to this method.
  246. @param catalog The catalog name.
  247. @param schemaPattern The schema name pattern.
  248. @param typeNamePattern The type name pattern.
  249. @param attributeNamePattern The attribute name pattern.
  250. @return The empty ResultSet
  251. @exception SQLException This exception is never thrown.
  252. @since Modification 5
  253. **/
  254. public ResultSet getAttributes (String catalog, String schemaPattern,
  255. String typeNamePattern, String attributeNamePattern)
  256. throws SQLException
  257. {
  258. // We return an empty result set because this is not supported by our driver
  259. Statement statement = connection_.createStatement();
  260. // TODO: Add this to all methods
  261. if (statement instanceof AS400JDBCStatement) {
  262. AS400JDBCStatement stmt= (AS400JDBCStatement) statement;
  263. stmt.closeOnCompletion();
  264. }
  265. ResultSet rs = statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " +
  266. "VARCHAR('2', 128) AS TYPE_SCHEM, " +
  267. "VARCHAR('3', 128) AS TYPE_NAME, " +
  268. "VARCHAR('4', 128) AS ATTR_NAME, " +
  269. "SMALLINT(5) AS DATA_TYPE, " +
  270. "VARCHAR('6', 128) AS ATTR_TYPE_NAME, " +
  271. "INT(7) AS ATTR_SIZE, " +
  272. "INT(8) AS DECIMAL_DIGITS, " +
  273. "INT(9) AS NUM_PREC_RADIX, " +
  274. "INT(10) AS NULLABLE, " +
  275. "VARCHAR('11', 128) AS REMARKS, " +
  276. "VARCHAR('12', 128) AS ATTR_DEF, " +
  277. "INT(13) AS SQL_DATA_TYPE, " +
  278. "INT(14) AS SQL_DATETIME_SUB, " +
  279. "INT(15) AS CHAR_OCTET_LENGTH, " +
  280. "INT(16) AS ORDINAL_POSITION, " +
  281. "VARCHAR('17', 128) AS IS_NULLABLE, " +
  282. "VARCHAR('18', 128) AS SCOPE_CATALOG, " +
  283. "VARCHAR('19', 128) AS SCOPE_SCHEMA, " +
  284. "VARCHAR('20', 128) AS SCOPE_TABLE, " +
  285. "SMALLINT(21) AS SOURCE_DATA_TYPE " +
  286. "FROM QSYS2" + getCatalogSeparator() +
  287. "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY ");
  288. return rs;
  289. }
  290. /**
  291. Returns a description of a table's optimal set of columns
  292. that uniquely identifies a row.
  293. @param catalog The catalog name. If null is specified, this parameter
  294. is ignored. If empty string is specified,
  295. an empty result set is returned.
  296. @param schema The schema name. If null is specified, the
  297. default SQL schema specified in the URL is used.
  298. If null is specified and a default SQL schema was not
  299. specified in the URL, the first library specified
  300. in the libraries properties file is used.
  301. If null is specified and a default SQL schema was
  302. not specified in the URL and a library was not
  303. specified in the libraries properties file,
  304. QGPL is used.
  305. If empty string is specified, an empty result set will
  306. be returned.
  307. @param table The table name. If null or empty string is specified,
  308. an empty result set is returned.
  309. @param scope The scope of interest. Valid values are:
  310. bestRowTemporary and bestRowTransaction.
  311. bestRowSession is not allowed because
  312. it cannot be guaranteed that
  313. the row will remain valid for the session.
  314. If bestRowSession is specified, an empty result
  315. set is returned.
  316. If bestRowTransaction is specified,
  317. autocommit is false, and transaction is set to repeatable read,
  318. then results is returned; otherwise, an empty result set
  319. is returned.
  320. @param nullable The value indicating if columns that are nullable should be included.
  321. @return The ResultSet containing a table's optimal
  322. set of columns that uniquely identify a row.
  323. @exception SQLException If the connection is not open
  324. or an error occurs.
  325. **/
  326. public ResultSet getBestRowIdentifier (String catalog,
  327. String schema,
  328. String table,
  329. int scope,
  330. boolean nullable)
  331. throws SQLException
  332. {
  333. connection_.checkOpen ();
  334. int vrm = connection_.getVRM(); //@trunc3
  335. DBReplyRequestedDS getBestRowIdentifierReply = null;
  336. //@mdsp SYSIBM SP Call
  337. if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
  338. {
  339. CallableStatement cstmt = connection_.prepareCall("call SYSIBM" + getCatalogSeparator () + "SQLSPECIALCOLUMNS(?,?,?,?,?,?,?)");
  340. cstmt.setShort(1, (short)SQL_BEST_ROWID);
  341. cstmt.setString(2, normalize(catalog));
  342. cstmt.setString(3, normalize(schema));
  343. cstmt.setString(4, normalize(table));
  344. cstmt.setShort(5, (short) scope);
  345. if (nullable) {
  346. cstmt.setShort(6, (short) SQL_NULLABLE);
  347. } else {
  348. cstmt.setShort(6, (short) SQL_NO_NULLS);
  349. }
  350. cstmt.setString(7,
  351. "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
  352. cstmt.execute();
  353. ResultSet rs = cstmt.getResultSet(); //@mdrs
  354. if(rs != null) //@mdrs
  355. ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
  356. else
  357. cstmt.close(); //@mdrs2
  358. return rs; //@mdrs
  359. }
  360. // Initialize the format of the result set.
  361. String[] fieldNames = { "SCOPE",
  362. "COLUMN_NAME",
  363. "DATA_TYPE",
  364. "TYPE_NAME",
  365. "COLUMN_SIZE",
  366. "BUFFER_LENGTH",
  367. "DECIMAL_DIGITS",
  368. "PSEUDO_COLUMN",
  369. };
  370. SQLData[] sqlData = { new SQLSmallint (vrm, settings_), // scope //@trunc3
  371. new SQLVarchar (128, settings_), // column name
  372. new SQLSmallint (vrm, settings_), // data type //@trunc3
  373. new SQLVarchar (128, settings_), // type name
  374. new SQLInteger (vrm, settings_), // column size //@trunc3
  375. new SQLInteger (vrm, settings_), // buffer length //@trunc3
  376. new SQLSmallint (vrm, settings_), // decimal digits //@trunc3
  377. new SQLSmallint (vrm, settings_), // pseudo column //@trunc3
  378. };
  379. int[] fieldNullables = { columnNoNulls, // scope
  380. columnNoNulls, // column name
  381. columnNoNulls, // data type
  382. columnNoNulls, // type name
  383. columnNoNulls, // column size
  384. columnNoNulls, // buffer length
  385. columnNoNulls, // decimal digits
  386. columnNoNulls, // pseudo column
  387. };
  388. JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
  389. JDRowCache rowCache = null;
  390. try
  391. {
  392. // Check for conditions that would result in an empty result set
  393. // Must check for null first to avoid NullPointerException
  394. if (!isCatalogValid(catalog) || // catalog is empty string
  395. // schema is not null and is empty string
  396. ((schema != null) && (schema.length()==0)) ||
  397. // Table is null
  398. (table==null) ||
  399. // Table is empty string
  400. (table.length()==0 ) ||
  401. // Scope.
  402. // If bestRowSession is specified, return empty set
  403. // since it can not be guaranteed that the row will
  404. // remain valid for the session.
  405. // If bestRowTemporary is specified, return results.
  406. // If bestRowTransaction is specified and autocommit
  407. // is true or transaction is not repeatableRead, return
  408. // empty result set
  409. ((scope == bestRowSession) ||
  410. ( (scope == bestRowTransaction) &&
  411. ( (connection_.getAutoCommit()==true) ||
  412. (connection_.getTransactionIsolation() != Connection.TRANSACTION_REPEATABLE_READ)))))
  413. { // Return empty result set
  414. rowCache = new JDSimpleRowCache(formatRow);
  415. }
  416. else
  417. { // parameter values are valid, build request & send
  418. // Create a request
  419. //@P0C
  420. DBReturnObjectInformationRequestDS request = null;
  421. try
  422. {
  423. request = DBDSPool.getDBReturnObjectInformationRequestDS (
  424. DBReturnObjectInformationRequestDS.FUNCTIONID_SPECIAL_COLUMN_INFO ,
  425. id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA +
  426. DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT +
  427. DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0);
  428. // Set the library name
  429. if (schema == null)
  430. { // use default SQL schema or qgpl
  431. request.setLibraryName(connection_.getDefaultSchema(), connection_.converter_); //@P0C
  432. }
  433. else request.setLibraryName(normalize(schema), connection_.converter_); // @E4C @P0C
  434. // Set the table name
  435. request.setFileName(normalize(table), connection_.converter_); // @E4C @P0C
  436. // Set the Field Information to Return Bitmap
  437. // Return library, table, and column
  438. request.setSpecialColumnsReturnInfoBitmap(0x1F000000);
  439. // Set the short / long file and field name indicator
  440. request.setFileShortOrLongNameIndicator(0xF0); // Long
  441. // Set if columns are nullable
  442. request.setSpecialColumnsNullableIndicator(nullable ?
  443. 0xF1 : 0xF0);
  444. //--------------------------------------------------------
  445. // Send the request and cache all results from the system
  446. //--------------------------------------------------------
  447. if (getBestRowIdentifierReply != null) { getBestRowIdentifierReply.returnToPool(); getBestRowIdentifierReply=null; }
  448. getBestRowIdentifierReply = connection_.sendAndReceive(request);
  449. // Check for errors - throw exception if errors were
  450. // returned
  451. int errorClass = getBestRowIdentifierReply.getErrorClass();
  452. if (errorClass !=0)
  453. {
  454. int returnCode = getBestRowIdentifierReply.getReturnCode();
  455. JDError.throwSQLException (this, connection_, id_,
  456. errorClass, returnCode);
  457. }
  458. // Get the data format and result data
  459. DBDataFormat dataFormat = getBestRowIdentifierReply.getDataFormat();
  460. DBData resultData = getBestRowIdentifierReply.getResultData();
  461. if (resultData != null)
  462. {
  463. JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_);
  464. JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE));
  465. JDFieldMap[] maps = new JDFieldMap[8];
  466. maps[0] = new JDHardcodedFieldMap(new Short ((short) scope)); // scope
  467. maps[1] = new JDSimpleFieldMap (1); // column name
  468. 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
  469. maps[3] = new JDSimpleFieldMap (2); // type name
  470. maps[4] = new JDSimpleFieldMap (4); // column size (length)
  471. maps[5] = new JDHardcodedFieldMap(new Integer (0)); // buffer length
  472. maps[6] = new JDSimpleFieldMap (5); // decimal digits (scale)
  473. maps[7] = new JDHardcodedFieldMap(new Short ((short) versionColumnNotPseudo));
  474. JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
  475. rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
  476. }
  477. else
  478. rowCache = new JDSimpleRowCache(formatRow);
  479. }
  480. finally
  481. {
  482. if (request != null) { request.returnToPool(); request = null; }
  483. // Cannot return to pool yet because array in use by resultData. Pased to result set to be closed there
  484. // if (getBestRowIdentifierReply != null) getBestRowIdentifierReply.returnToPool();
  485. }
  486. }
  487. }
  488. catch (DBDataStreamException e)
  489. {
  490. JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
  491. }
  492. return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "BestRowIdentifier", connection_, getBestRowIdentifierReply); //@in2
  493. }
  494. /**
  495. Returns the catalog name available in this database. This
  496. will return a ResultSet with a single row, whose value is
  497. the IBM i system name.
  498. @return The ResultSet containing the IBM i system name.
  499. @exception SQLException If the connection is not open
  500. or an error occurs.
  501. **/
  502. public ResultSet getCatalogs ()
  503. throws SQLException
  504. {
  505. connection_.checkOpen ();
  506. //@mdsp SYSIBM SP Call
  507. if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
  508. {
  509. CallableStatement cstmt = connection_.prepareCall("CALL SYSIBM" + getCatalogSeparator() + "SQLTABLES(?,?,?,?,?)");
  510. cstmt.setString(1, "%");
  511. cstmt.setString(2, "%");
  512. cstmt.setString(3, "%");
  513. cstmt.setString(4, "%");
  514. cstmt.setString(5, "DATATYPE='JDBC';GETCATALOGS=1;CURSORHOLD=1");
  515. cstmt.execute();
  516. ResultSet rs = cstmt.getResultSet(); //@mdrs
  517. if(rs != null) //@mdrs
  518. ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
  519. else
  520. cstmt.close(); //@mdrs2
  521. return rs; //@mdrs
  522. }
  523. String[] fieldNames = {"TABLE_CAT"};
  524. SQLData[] sqlData = { new SQLVarchar (128, settings_)};
  525. int[] fieldNullables = {columnNoNulls}; // Catalog Name
  526. JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
  527. Object[][] data = { { connection_.getCatalog()}};
  528. boolean[][] nulls = {{false}};
  529. boolean[][] dataMappingErrors = {{false}};
  530. // If running to a system running OS/400 v5r2 or IBM i the list can contain more than just the system
  531. // name (when IASPs are on the system). Try to retrieve that list. Note
  532. // if getting the list fails we will still return a result set containing
  533. // one item -- the name of the system. We just built that result set
  534. // (the previous six lines of code) and that is what we will return. That
  535. // result set will be consistent with the result set returned when connecting
  536. // to OS/400 v5r1 or earlier versions. If getting the list works we will
  537. // build and return a new result set containing data retrieved from the system.
  538. if (connection_.getVRM() >= JDUtilities.vrm520) // @F1a
  539. { // @F1a
  540. try
  541. { // @F1a // @F1a
  542. Vector RDBEntries = new Vector(); // @F1a
  543. Statement statement = null; //@scan1
  544. ResultSet rs = null; //@scan1
  545. try
  546. {
  547. statement = connection_.createStatement(); // @F1a
  548. rs = statement.executeQuery("SELECT LOCATION FROM QSYS2" + getCatalogSeparator() + "SYSCATALOGS WHERE RDBTYPE = 'LOCAL' AND RDBASPSTAT='AVAILABLE' "); // @F1a
  549. while (rs.next()) // @F1a
  550. { // @F1a
  551. RDBEntries.add(rs.getString(1).trim()); // @F1a
  552. }
  553. }finally //@scan1
  554. {
  555. try{
  556. if(rs != null)
  557. rs.close();
  558. }catch(Exception e){} //allow next close to execute
  559. if(statement != null)
  560. statement.close();
  561. }
  562. int count = RDBEntries.size(); // @F1a
  563. if (count > 0) // @F1a
  564. { // @F1a
  565. data = new Object[count][1]; // @F1a
  566. nulls = new boolean[count][1]; // @F1a
  567. dataMappingErrors = new boolean[count][1];
  568. for (int i=0; i<count; i++) // @F1a
  569. { // @F1a
  570. data[i][0] = RDBEntries.elementAt(i); // @F1a
  571. nulls[i][0] = false; // @F1a
  572. dataMappingErrors[i][0] = false;
  573. } // @F1a
  574. } // @F1a
  575. else
  576. { // @F1a // @F1a
  577. if (JDTrace.isTraceOn()) // @F1a
  578. JDTrace.logInformation (this, "Could not retrieve list of RDBs from system (count = 0)."); // @F1a
  579. } // @F1a
  580. } // @F1a
  581. catch (Exception e) // @F1a
  582. { // @F1a
  583. if (JDTrace.isTraceOn()) // @F1a
  584. JDTrace.logInformation (this, "Could not retrieve list of RDBs from system (exception)."); // @F1a
  585. } // @F1a
  586. } // @F1a
  587. JDSimpleRowCache rowCache = new JDSimpleRowCache (formatRow, data, nulls, dataMappingErrors);
  588. return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "Catalogs", connection_, null); //@in2
  589. }
  590. /**
  591. Returns the naming convention used when referring to tables.
  592. This depends on the naming convention specified in the connection
  593. properties.
  594. @return If using SQL naming convention, "." is returned. If
  595. using system naming convention, "/" is returned.
  596. @exception SQLException This exception is never thrown.
  597. **/
  598. public String getCatalogSeparator ()
  599. throws SQLException
  600. {
  601. String catalogSeparator;
  602. if (connection_.getProperties().equals (JDProperties.NAMING, JDProperties.NAMING_SQL))
  603. catalogSeparator = ".";
  604. else
  605. catalogSeparator = "/";
  606. return catalogSeparator;
  607. }
  608. /**
  609. Returns the DB2 for IBM i SQL term for "catalog".
  610. @return The term "System".
  611. @exception SQLException This exception is never thrown.
  612. **/
  613. public String getCatalogTerm ()
  614. throws SQLException
  615. {
  616. return AS400JDBCDriver.getResource ("CATALOG_TERM");
  617. }
  618. /**
  619. Returns a description of the access rights for a table's columns.
  620. @param catalog The catalog name. If null is specified, this parameter
  621. is ignored. If empty string is specified,
  622. an empty result set is returned.
  623. @param schema The schema name. If null is specified, the
  624. default SQL schema specified in the URL is used.
  625. If null is specified and a default SQL schema was not
  626. specified in the URL, the first library specified
  627. in the libraries properties file is used.
  628. If null is specified and a default SQL schema was
  629. not specified in the URL and a library was not
  630. specified in the libraries properties file,
  631. QGPL is used.
  632. If empty string is specified, an empty result set will
  633. be returned.
  634. @param table The table name. If null or empty string is specified,
  635. an empty result set is returned.
  636. @param columnPattern The column name pattern. If null is specified,
  637. no value is sent to the system and the system
  638. default of *all is used. If empty string
  639. is specified, an empty result set is returned.
  640. @return The ResultSet containing access rights for a
  641. table's columns.
  642. @exception SQLException If the connection is not open
  643. or an error occurs.
  644. **/
  645. public ResultSet getColumnPrivileges (String catalog,
  646. String schema,
  647. String table,
  648. String columnPattern)
  649. throws SQLException
  650. {
  651. connection_.checkOpen ();
  652. // int vrm = connection_.getVRM(); //@trunc3
  653. //@mdsp SYSIBM SP Call - move block to top of method
  654. if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
  655. {
  656. //@PDC change to use sysibm.sqlcolprivileges stored procedure
  657. // Set the library name
  658. //@mdsp follow Native JDBC logic
  659. /*if (schema == null)
  660. { // use default SQL schema or qgpl
  661. schema = normalize(connection_.getDefaultSchema());
  662. }
  663. else schema = normalize(schema);
  664. // Set the table name
  665. table = normalize(table);
  666. */
  667. // Set the column name and search pattern
  668. // If null, do not set parameter. The system default
  669. // value of *ALL is used.
  670. CallableStatement cstmt = connection_.prepareCall("call SYSIBM" + getCatalogSeparator () + "SQLCOLPRIVILEGES (?, ?, ?, ?, ?)");
  671. cstmt.setString(1, normalize(catalog));
  672. cstmt.setString(2, normalize(schema));
  673. cstmt.setString(3, normalize(table));
  674. cstmt.setString(4, normalize(columnPattern));
  675. cstmt.setObject(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@pdc options per db2 common design. //@mdsp more native synch
  676. ResultSet rs = cstmt.executeQuery();
  677. if(rs != null) //@mdrs
  678. ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
  679. else
  680. cstmt.close(); //@mdrs2
  681. return rs; //@mdrs
  682. }
  683. //--------------------------------------------------------
  684. // Set up the result set in the format required by JDBC
  685. //--------------------------------------------------------
  686. String[] fieldNames = {"TABLE_CAT",
  687. "TABLE_SCHEM",
  688. "TABLE_NAME",
  689. "COLUMN_NAME",
  690. "GRANTOR",
  691. "GRANTEE",
  692. "PRIVILEGE",
  693. "IS_GRANTABLE",
  694. };
  695. SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog
  696. new SQLVarchar (128, settings_), // library
  697. new SQLVarchar (128, settings_), // table
  698. new SQLVarchar (128, settings_), // column
  699. new SQLVarchar (128, settings_), // grantor
  700. new SQLVarchar (128, settings_), // grantee
  701. new SQLVarchar (128, settings_), // privilege
  702. new SQLVarchar (3, settings_), // is_grantable
  703. };
  704. int[] fieldNullables = {columnNullable, // catalog
  705. columnNullable, // library
  706. columnNoNulls, // table
  707. columnNoNulls, // column
  708. columnNullable, // grantor
  709. columnNoNulls, // grantee
  710. columnNoNulls, // privilege
  711. columnNullable, // is_grantable
  712. };
  713. JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
  714. JDRowCache rowCache = null; // Creates a set of rows
  715. // that are readable one at a time.
  716. // Check for conditions that would result in an empty result set
  717. // Must check for null first to avoid NullPointerException
  718. if (!isCatalogValid(catalog) || // catalog is empty string
  719. // schema is not null and is empty string
  720. ((schema != null) && (schema.length()==0)) ||
  721. // Table is null
  722. table==null ||
  723. // Table is empty string
  724. table.length()==0 ||
  725. // columnPattern is not null and is empty string
  726. ((columnPattern != null) && (columnPattern.length()==0)))
  727. { // Return empty result set
  728. rowCache = new JDSimpleRowCache (formatRow);
  729. return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "ColumnPrivileges", connection_, null); //@in2 //@PDC
  730. }
  731. else
  732. {
  733. // parameter values are valid, build request & send
  734. // Create a request
  735. //@P0C
  736. DBReturnObjectInformationRequestDS request = null;
  737. DBReplyRequestedDS reply = null;
  738. try
  739. {
  740. request = DBDSPool.getDBReturnObjectInformationRequestDS (
  741. DBReturnObjectInformationRequestDS.FUNCTIONID_FIELD_INFO,
  742. id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA +
  743. DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT +
  744. DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0);
  745. // Set the library name
  746. if (schema == null)
  747. { // use default SQL schema or qgpl
  748. request.setLibraryName(normalize(connection_.getDefaultSchema()), connection_.converter_); // @E4C @P0C
  749. }
  750. else request.setLibraryName(normalize(schema), connection_.converter_); // @E4C @P0C
  751. // Set the table name
  752. request.setFileName(normalize(table), connection_.converter_); // @E4C @P0C
  753. // Set the column name and search pattern
  754. // If null, do not set parameter. The system default
  755. // value of *ALL is used.
  756. if (!(columnPattern==null))
  757. {
  758. JDSearchPattern column = new JDSearchPattern(columnPattern);
  759. request.setFieldName(column.getPatternString(), connection_.converter_); //@P0C
  760. request.setFieldNameSearchPatternIndicator(column.getIndicator());
  761. }
  762. // Set the Field Information to Return Bitmap
  763. // Return library, table, and column
  764. request.setFieldReturnInfoBitmap(0xA8000000);
  765. // Set the short / long file and field name indicator
  766. request.setFileShortOrLongNameIndicator(0xF0); // Long
  767. // Set the Field Information Order By Indicator parameter
  768. // Order by: Schema and File
  769. request.setFileInfoOrderByIndicator (2);
  770. //--------------------------------------------------------
  771. // Send the request and cache all results from the system
  772. //--------------------------------------------------------
  773. reply = connection_.sendAndReceive(request);
  774. // Check for errors - throw exception if errors were
  775. // returned
  776. int errorClass = reply.getErrorClass();
  777. if (errorClass !=0)
  778. {
  779. int returnCode = reply.getReturnCode();
  780. JDError.throwSQLException (this, connection_, id_,
  781. errorClass, returnCode);
  782. }
  783. // Get the data format and result data
  784. DBDataFormat dataFormat = reply.getDataFormat();
  785. DBData resultData = reply.getResultData();
  786. if (resultData != null)
  787. {
  788. JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_);
  789. JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE));
  790. // Create the mapped row format that is returned in the
  791. // result set.
  792. // This does not actual move the data, it just sets up
  793. // the mapping.
  794. JDFieldMap[] maps = new JDFieldMap[8];
  795. maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ());
  796. maps[1] = new JDSimpleFieldMap (1); // library
  797. maps[2] = new JDSimpleFieldMap (2); // table
  798. maps[3] = new JDSimpleFieldMap (3); // column
  799. maps[4] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_), true, false ); // grantor
  800. maps[5] = new JDHardcodedFieldMap (getUserName ()); // grantee - return userid
  801. maps[6] = new JDHardcodedFieldMap(""); // privilege
  802. maps[7] = new JDHardcodedFieldMap(new SQLVarchar(0, settings_),true, false ); // is_grantable
  803. // Create the mapped row cache that is returned in the
  804. // result set
  805. JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
  806. rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
  807. }
  808. else
  809. rowCache = new JDSimpleRowCache(formatRow);
  810. } catch (DBDataStreamException e)
  811. {
  812. if (reply != null) { reply.returnToPool(); reply = null; }
  813. JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
  814. }
  815. finally
  816. {
  817. if (request != null) { request.returnToPool(); request = null; }
  818. // if (reply != null) { reply.returnToPool(); reply = null; }
  819. }
  820. // Return the results
  821. return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "ColumnPrivileges", connection_, reply); //@in2
  822. } // End of else to build and send request
  823. }
  824. /**
  825. Returns a description of the table's columns available in a
  826. catalog.
  827. @param catalog The catalog name. If null is specified, this parameter
  828. is ignored. If empty string is specified,
  829. an empty result set is returned.
  830. @param schemaPattern The schema name pattern.
  831. If the "metadata source" connection property is set to 0
  832. and null is specified, no value is sent to the system and
  833. the default of *USRLIBL is used.
  834. If the "metadata source" connection property is set to 1
  835. and null is specified, then information from all schemas
  836. will be returned.
  837. If an empty string
  838. is specified, an empty result set is returned.
  839. @param tablePattern The table name pattern. If null is specified,
  840. no value is sent to the system and the system
  841. default of *ALL is used. If empty string
  842. is specified, an empty result set is returned.
  843. @param columnPattern The column name pattern. If null is specified,
  844. no value is sent to the system and the system
  845. default of *ALL is used. If empty string
  846. is specified, an empty result set is returned.
  847. @return The ResultSet containing the table's columns available
  848. in a catalog.
  849. @exception SQLException If the connection is not open
  850. or an error occurs.
  851. **/
  852. public ResultSet getColumns (String catalog,
  853. String schemaPattern,
  854. String tablePattern,
  855. String columnPattern)
  856. throws SQLException
  857. {
  858. DBReplyRequestedDS reply = null;
  859. connection_.checkOpen ();
  860. boolean isJDBC3 = JDUtilities.JDBCLevel_ >= 30; //@F2A @j4a
  861. String[] fieldNames = null; //@F2C
  862. SQLData[] sqlData = null; //@F2C
  863. int[] fieldNullables = null; //@F2C
  864. //@F2A Result sets must be different depending on whether we are running under JDBC 3.0
  865. //@pda jdbc40 is also contained in same block as jdbc30, since this file is jdbc40 only compiled.
  866. int vrm = connection_.getVRM(); //@trunc3
  867. //@mdsp SYSIBM SP Call
  868. if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
  869. {
  870. CallableStatement cs = connection_.prepareCall("CALL SYSIBM" + getCatalogSeparator() + "SQLCOLUMNS(?,?,?,?,?)");
  871. cs.setString(1, normalize(catalog));
  872. cs.setString(2, normalize(schemaPattern));
  873. cs.setString(3, normalize(tablePattern));
  874. cs.setString(4, normalize(columnPattern));
  875. /* ifdef JDBC40 */
  876. // Use 4.1 if JDBC version is 4.1
  877. if (javaVersion > 16) {
  878. cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.1';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4
  879. } else {
  880. cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4
  881. }
  882. /* endif */
  883. /* ifndef JDBC40
  884. cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
  885. endif */
  886. cs.execute();
  887. ResultSet rs = cs.getResultSet(); //@mdrs
  888. if(rs != null) //@mdrs
  889. ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
  890. else
  891. cs.close(); //@mdrs2
  892. return rs; //@mdrs
  893. // Create an return the result set for the request.
  894. // Note: This will failed until SQLCOLUMNS returns more columns
  895. // return new DB2RSGetColumns40(x, isTransactional);
  896. }
  897. if (!isJDBC3) //@F2A
  898. {
  899. // Set up the result set in the format required by JDBC
  900. fieldNames = new String[] {"TABLE_CAT",
  901. "TABLE_SCHEM",
  902. "TABLE_NAME",
  903. "COLUMN_NAME",
  904. "DATA_TYPE",
  905. "TYPE_NAME",
  906. "COLUMN_SIZE",
  907. "BUFFER_LENGTH",
  908. "DECIMAL_DIGITS",
  909. "NUM_PREC_RADIX",
  910. "NULLABLE",
  911. "REMARKS",
  912. "COLUMN_DEF",
  913. "SQL_DATA_TYPE",