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

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

The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: AS400JDBCResultSetMetaData.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.Connection;
/* ifdef JDBC40
import java.sql.DatabaseMetaData;
endif */
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
/* ifdef JDBC40
import java.sql.Statement;
endif */


/**

The AS400JDBCResultSetMetaData class describes the columns in a result set. **/ // // Implementation notes: // // * I lifted the restriction that a result set be open when // using this object, specifically so it could be used after // preparing but before executing (via PreparedStatement.getMetaData()). // // * I also removed the reference to the result set as private // data. This is again because of the need to create this object // before executing a query (via PreparedStatement.getMetaData()). // public class AS400JDBCResultSetMetaData /* ifdef JDBC40 extends ToolboxWrapper endif */ implements ResultSetMetaData { static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others."; // Private static final ints // Searchable constants //@G1A @G2C static final int SQL_UNSEARCHABLE = 0xF0; // isSearchable = false static final int SQL_LIKE_ONLY = 0xF1; // will not be returned by our IBM i system static final int SQL_ALL_EXCEPT_LIKE = 0xF2; // isSearchable = true static final int SQL_SEARCHABLE = 0xF3; // isSearchable = true // Updateable constants //@G1A @G2C static final int SQL_READ_ONLY = 0xF0; // isReadOnly = true, isWriteable = false static final int SQL_WRITE_CAPABLE = 0xF1; // isReadOnly = false, isWriteable = true static final int SQL_READ_WRITE_UNKNOWN = 0xF2; // will not be returned by our IBM i system // Private data. private String catalog_; private int concurrency_; private String cursorName_; private JDRow row_; private DBExtendedColumnDescriptors extendedColumnDescriptors_; //@G1A private ConvTable convTable_; //@G1A private AS400JDBCConnection con_; //@in1 SQLConversionSettings settings_; /*@Q8A*/ /** Constructs an AS400JDBCResultSetMetaData object. @param catalog The catalog. @param concurrency The result set concurrency. @param cursorName The cursor name. @param row The row. @param extendedColumnDescriptors The extended column descriptors. @param convTable The converter table to use to convert column descriptors. * @throws SQLException If a database error occurs. **/ AS400JDBCResultSetMetaData(String catalog, int concurrency, String cursorName, JDRow row, DBExtendedColumnDescriptors extendedColumnDescriptors, //@G1A ConvTable convTable, //@G1A AS400JDBCConnection con) throws SQLException //@in1 { catalog_ = catalog; concurrency_ = concurrency; cursorName_ = cursorName; row_ = row; extendedColumnDescriptors_ = extendedColumnDescriptors; //@G1A convTable_ = convTable; //@G1A con_ = con; //@in1 settings_ = SQLConversionSettings.getConversionSettings ( con_); /*@Q8A*/ } /** Throws an exception if the specified column index is not valid. @param columnIndex The column index (1-based). @exception SQLException If the column index is not valid. **/ private void checkIndex(int columnIndex) throws SQLException { // Validate the column index. if((columnIndex < 1)) JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID,columnIndex+"<1"); if((columnIndex > row_.getFieldCount())) JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID, columnIndex+">"+row_.getFieldCount()); } /** Returns the catalog name of the table for a column. @param columnIndex The column index (1-based). @return The catalog name. @exception SQLException If the column index is not valid. **/ public String getCatalogName(int columnIndex) throws SQLException { checkIndex(columnIndex); return catalog_; } // JDBC 2.0 /** Returns the name of a Java class whose instances are created if ResultSet.getObject() is called to retrieve from the column. The actual class created may be a subclass of the returned class. @param columnIndex The column index (1-based). @return The class name. @exception SQLException If the column index is not valid. **/ // // Implementation note: // // * In the case where the column returns a byte array, this // returns "[B". See the javadoc for java.lang.Class.getName() // for the reason why. The JDBC 2.0 specification does not // really go into detail, so it is unclear if this is okay // to return. I will assume so in the mean time. // public String getColumnClassName(int columnIndex) throws SQLException { checkIndex(columnIndex); SQLData sqlData = row_.getSQLType(columnIndex); String className = sqlData.getObject().getClass().getName(); return className; } /** Returns the number of columns in the result set. @return The number of columns. @exception SQLException If an error occurs. **/ public int getColumnCount() throws SQLException { return row_.getFieldCount(); } /** Returns the normal maximum width of a column. @param columnIndex The column index (1-based). @return The normal maximum width (in characters). @exception SQLException If the column index is not valid. **/ public int getColumnDisplaySize(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getSQLType(columnIndex).getDisplaySize(); } /** Returns the suggested label for use in printouts or displays for a column. @param columnIndex The column index (1-based). @return The column label if the user set the driver property "extended metadata" to true and the system returns us a column label, otherwise the column name. @exception SQLException If the column index is not valid. **/ // // Implementation note: // // For now, this is the same as the field name. In // order to get the field label, we would have to make // an extra request to the ROI server and perform a lot // of extra processing. This performance hit is not // worth it. If the caller really needs the label, then // they can use DatabaseMetaData.getColumns. // // As of mod5 of Toolbox, we can use extended column descriptors // (if the user asked for the by setting the "extended metadata" property // to true) which will flow back to us without an extra call to the ROI server. // public String getColumnLabel(int columnIndex) throws SQLException { checkIndex(columnIndex); // @G1A If we have column descriptors, use them to get the column label. //@G1A if(extendedColumnDescriptors_ != null) //@G1A { //@G1A DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_, settings_); //@KBA //@Q8C // Fix for JTOpen Bug 4034 The ccsid for the column may be 65535, if that is the case, we want to use the job's ccsid if(dataFormat != null) //@KBA The data format returned by the host server will be null for columns created by expressions, use old way { //@D9A String columnLabel = dataFormat.getColumnLabel(convTable_); //@D9A // Only return if the returned label length is greater than zero if(columnLabel != null && columnLabel.length() > 0) //@D9A@P6C return columnLabel; //@D9A //@D9D return dataFormat.getColumnLabel(convTable_); //@KBA //@KBD return extendedColumnDescriptors_.getColumnDescriptors(columnIndex).getColumnLabel(convTable_); //@G1A } } //@G1A //else use the "old way". return row_.getFieldName(columnIndex); } /** Returns the name of a column. @param columnIndex The column index (1-based). @return The column name. @exception SQLException If the column index is not valid. **/ public String getColumnName(int columnIndex) throws SQLException { checkIndex(columnIndex); String columnName =row_.getFieldName(columnIndex); if (JDTrace.isTraceOn()) { JDTrace.logInformation (this, "getColumnName("+columnIndex+") returned " + columnName); } return columnName; } /** Returns the type of a column. If the type is a distinct type, this returns the underlying type. @param columnIndex The column index (1-based). @return The SQL type code defined in java.sql.Types. @exception SQLException If the column index is not valid. **/ public int getColumnType(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getSQLType(columnIndex).getType(); } /** Returns the CCSID of a character column. Returns 0 if the column is not a character column. @param columnIndex The column index (1-based). @return CCSID of a character column, otherwise 0. @exception SQLException If the column index is not valid. **/ /* @V8A */ public int getColumnCCSID(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getCCSID(columnIndex); } /** Returns the type name of a column. If the type is a distinct type, this returns the underlying type name. @param columnIndex The column index (1-based). @return The column type name. @exception SQLException If the column index is not valid. **/ public String getColumnTypeName(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getSQLTypeName(columnIndex); /*@L1C*/ } /** Returns the precision of a column. This is the number of decimal digits the column may hold. @param columnIndex The column index (1-based). @return The precision. @exception SQLException If the column index is not valid. **/ public int getPrecision(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getSQLType(columnIndex).getPrecision(); } /** Returns the scale of a column. This is number of digits to the right of the decimal point. @param columnIndex The column index (1-based). @return The scale. @exception SQLException If the column index is not valid. **/ public int getScale(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.getSQLType(columnIndex).getScale(); } /** Returns the schema name of the table for a column. This method is supported only if the user has set the driver property "extended metadata" to true. @param columnIndex The column index (1-based). @return The schema name if the user set the driver property "extended metadata" to true and the system returns us a schema name, otherwise "". @exception SQLException If the column index is not valid. **/ public String getSchemaName(int columnIndex) throws SQLException { checkIndex(columnIndex); // @G1A If we have column descriptors, use them to get the schema name. //@G1A if(extendedColumnDescriptors_ != null) //@G1A { //@G1A DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_,settings_); //@KBA //@ss1//@Q8C if(dataFormat != null) //@KBA Depending on the query, dataFormat returned by the host server may be null. For example, if a union was used or an expression return dataFormat.getBaseTableSchemaName(convTable_); //@G1A } //@G1A //else return "" return ""; } /** Returns the column's table name. This method is supported only if the user has set the driver property "extended metadata" to true. @param columnIndex The column index (1-based). @return The base table name if the user set the driver property "extended metadata" to true and the system returns us a table name, otherwise "". @exception SQLException If the column index is not valid. **/ public String getTableName(int columnIndex) throws SQLException { checkIndex(columnIndex); // Changed to get the Base Table Name for a column if the extended metadata property is true // because we already have the information, we should return it to the user if they want it... if(extendedColumnDescriptors_ != null) { DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_, settings_); //@KBA //@ss1 //@Q8C if(dataFormat != null) //@KBA Depending on the query, dataFormat returned by the host server may be null. For example, if a union was used or an expression return dataFormat.getBaseTableName(convTable_); //@KBA //@KBD return extendedColumnDescriptors_.getColumnDescriptors(columnIndex).getBaseTableName(convTable_); //K1C use to call getBaseTableSchemaName } // we still return "" if we don't have the Base Table Name return ""; } /** Indicates if the column is automatically numbered. @param columnIndex The column index (1-based). @return True if column is autoincrement, false otherwise. @exception SQLException If the column index is not valid. Note: connection property "extended metadata" must be true for this method to be return accurate information. If the "extended metadata" connection property is not set to true, then this method will always return false. **/ public boolean isAutoIncrement(int columnIndex) throws SQLException { checkIndex(columnIndex); // Only run the query to get the information if the table name can be found. The table name // can only be found if "extended metadata" == true // @A9A String tableName = this.getTableName(columnIndex); if ((tableName == null) || (tableName.length() == 0) ) { return false; } //return false; //@in1 add implementation instead of always returning false PreparedStatement ps = null; ResultSet rs = null; try { ps = con_.prepareStatement("SELECT identity_generation " + "FROM QSYS2" + getCatalogSeparator() + "SYSCOLUMNS" + " WHERE identity_generation is not null" + " AND column_name = ?" + " AND table_name = ?" + " AND table_schema = ?"); ps.setString(1, this.getColumnName(columnIndex)); ps.setString(2, tableName); ps.setString(3, this.getSchemaName(columnIndex)); rs = ps.executeQuery(); if ( rs.next()) return true; else return false; } catch (SQLException e) { throw e; } finally { try{ if(rs != null) rs.close(); }catch(Exception e){ JDTrace.logException(this, "isAutoIncrement rs.close()", e); } //allow next close to execute if(ps != null) ps.close(); } } /** Indicates if the column is case sensitive. @param columnIndex The column index (1-based). @return true if the column is case sensitive; false otherwise. @exception SQLException If the column index is not valid. **/ public boolean isCaseSensitive(int columnIndex) throws SQLException { checkIndex(columnIndex); // In DB2 for IBM i, all text types // are case sensitive. return row_.getSQLType(columnIndex).isText(); } /** Indicates if the column is a currency value. @param columnIndex The column index (1-based). @return Always false. DB2 for IBM i does not directly support currency values. @exception SQLException If the column index is not valid. **/ public boolean isCurrency(int columnIndex) throws SQLException { checkIndex(columnIndex); return false; } /** Indicates if a write on the column will definitely succeed. @param columnIndex The column index (1-based). @return Always false. The driver does not check if the user has the necessary authority to write to the column. @exception SQLException If the column index is not valid. **/ public boolean isDefinitelyWritable(int columnIndex) throws SQLException { checkIndex(columnIndex); return false; } /** Indicates if the column can contain an SQL NULL value. @param columnIndex The column index (1-based). @return true if the column is can contain an SQL NULL value; false otherwise. @exception SQLException If the column index is not valid. **/ public int isNullable(int columnIndex) throws SQLException { checkIndex(columnIndex); return row_.isNullable(columnIndex); } /** Indicates if the column is read-only. @param columnIndex The column index (1-based). @return true if the column is read-only; false otherwise. @exception SQLException If the column index is not valid. **/ public boolean isReadOnly(int columnIndex) throws SQLException { checkIndex(columnIndex); // @G1A If we have column descriptors, use them to get searchable label. //@G1A if(extendedColumnDescriptors_ != null)// && concurrency_ != ResultSet.CONCUR_READ_ONLY) //@G1A @G3C @36072 { //@G1A if(extendedColumnDescriptors_.getUpdateable(columnIndex) == (byte)SQL_READ_ONLY) //@G1A @G2C return true; //@G1A else //@G1A return false; //@G1A } //@G1A // else use "old" way return(concurrency_ == ResultSet.CONCUR_READ_ONLY); } /** Indicates if the column be used in a where clause. @param columnIndex The column index (1-based). @return If the user has set the "extended metadata" driver property to true, returns true if the column can be used in a where clause with any comparison operator except LIKE, returns false if the column cannot be used in a where clause. If the "extended metadata" driver property is set to false, true will always be returned. @exception SQLException If the column index is not valid. **/ public boolean isSearchable(int columnIndex) throws SQLException { checkIndex(columnIndex); // @G1A If we have column descriptors, use them to get searchable label. //@G1A if(extendedColumnDescriptors_ != null) //@G1A { //@G1A if(extendedColumnDescriptors_.getSearchable(columnIndex) == (byte)SQL_UNSEARCHABLE) //@G1A @G2C return false; //@G1A else //@G1A return true; //@G1A } //@G1A // Else, return true return true; } /** Indicates if the column can contain a signed value. @param columnIndex The column index (1-based). @return true if the column is signed; false otherwise. @exception SQLException If the column index is not valid. **/ public boolean isSigned(int columnIndex) throws SQLException { checkIndex(columnIndex); return(row_.getSQLType(columnIndex).isSigned()); } /** Indicates if it is possible for a write on the column to succeed. The write may fail even if this method returns true. The accuracy of this method will be improved if the "extended metadata" property is set to true. @param columnIndex The column index (1-based). @return true if it is possible for a write on the column to succeed; false otherwise. @exception SQLException If the column index is not valid. **/ public boolean isWritable(int columnIndex) throws SQLException { //@G1D checkIndex (columnIndex); //@G1D return(concurrency_ != ResultSet.CONCUR_READ_ONLY); return !isReadOnly(columnIndex); //@G1A } /** Returns the name of the SQL cursor in use by this result set. @return The cursor name. **/ public String toString() { return cursorName_; } //@pda jdbc40 protected String[] getValidWrappedList() { return new String[] { "com.ibm.as400.access.AS400JDBCResultSetMetaData", "java.sql.ResultSetMetaData" }; } //@in1 (copied from AS400JDBCDatabaseMetadata) /** Returns the naming convention used when referring to tables. This depends on the naming convention specified in the connection properties. @return If using SQL naming convention, "." is returned. If using system naming convention, "/" is returned. @exception SQLException This exception is never thrown. **/ private String getCatalogSeparator () throws SQLException { String catalogSeparator; if (con_.getProperties().equals (JDProperties.NAMING, JDProperties.NAMING_SQL)) catalogSeparator = "."; else catalogSeparator = "/"; return catalogSeparator; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy