diff --git a/jdbc40/.classpath b/jdbc40/.classpath new file mode 100644 index 000000000..f8367783f --- /dev/null +++ b/jdbc40/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/jdbc40/.externalToolBuilders/build build.xml [Builder].launch b/jdbc40/.externalToolBuilders/build build.xml [Builder].launch new file mode 100644 index 000000000..fcd2607cc --- /dev/null +++ b/jdbc40/.externalToolBuilders/build build.xml [Builder].launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/jdbc40/.project b/jdbc40/.project new file mode 100644 index 000000000..04747b71e --- /dev/null +++ b/jdbc40/.project @@ -0,0 +1,18 @@ + + + jdbc40 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + + diff --git a/jdbc40/.settings/org.eclipse.jdt.core.prefs b/jdbc40/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..00d179b9c --- /dev/null +++ b/jdbc40/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,70 @@ +#Wed Mar 03 11:07:23 CST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/jdbc40/.settings/org.eclipse.ltk.core.refactoring.prefs b/jdbc40/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 000000000..a58eda8d4 --- /dev/null +++ b/jdbc40/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Thu Jan 28 11:31:44 CST 2010 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCArrayResultSet.java b/jdbc40/com/ibm/as400/access/AS400JDBCArrayResultSet.java new file mode 100644 index 000000000..85e631524 --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCArrayResultSet.java @@ -0,0 +1,4354 @@ +/////////////////////////////////////////////////////////////////////////////// + +//JTOpen (IBM Toolbox for Java - OSS version) + +//Filename: AS400JDBCArrayResultSet.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) 2009-2009 International Business Machines Corporation and +//others. All rights reserved. + +/////////////////////////////////////////////////////////////////////////////// +package com.ibm.as400.access; + + +import java.io.InputStream; +import java.io.Reader; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.*; + +//@array new class +/** AS400JDBCArrayResultSet is a JDBC ResultSet that contains Array data. This is a client-side only object. This is used to navigating through + * returned data from IBM i DB2 using Toolbox JDBC. No updates will be functional nor will they be sent back to the host server. + * Note that this ResultSet is limited in its functionality since it is not tied back to a cursor in the database. + * Its primary purpose is for retrieving data back from the database. + **/ +public class AS400JDBCArrayResultSet +/* ifdef JDBC40 */ +extends ToolboxWrapper +/* endif */ +implements ResultSet +{ + + private int holdability_; // Used by JDBC 40 + private int concurrency_; + private int fetchDirection_; + private int fetchSize_; + private int type_; + /* same as in AS400JDBCArray, the data_ array contains either Objects or SQLData. If SQLData, then it will + * do any needed conversion between types. If the data is an Ojbect (like Integer), then we will not do any + * conversion. + */ + private Object[][] data_; // column based data. + private int numberOfColumns_; + private int numberOfRows_; + private java.util.HashMap columnNameToIndexCache_; + + + //////Info from AS400JDBCArray + + private SQLData contentTemplate_; + private boolean isSQLData_; + + private int vrm_; + AS400JDBCConnection con_; //future use + /////////////////// + + + private boolean openOnClient_; + private int currentRowInRowset_; + private int wasNull_; + + + private java.util.Calendar calendar_; + private Class byteArrayClass_; + static final private int WAS_NULL_UNSET = 0; + static final private int WAS_NULL = 1; + static final private int WAS_NOT_NULL = 2; + + /** + Constructs an AS400JDBCArrayResultSet object. + + @param contents An java array of data. + @param contentTemplate An instance of SQLData child class. + @param isSQLData Specifies if contents array content is an SQLData subclass type. + @param dataType Data type. + @param vrm Version + @param con Connection. + **/ + AS400JDBCArrayResultSet ( Object[] contents , SQLData contentTemplate, boolean isSQLData, int dataType, int vrm, AS400JDBCConnection con) + { + Object[][] data = new Object[2][]; + // initialize "INDEX" column + if(isSQLData) + { + data[0] = new SQLInteger[contents.length]; //@arrayrs //since array data will be sqlX, then make the index sqlInteger also + for (int i = 0; i < contents.length; i++) + { + try{ + SQLInteger si = (SQLInteger)SQLDataFactory.newData("INTEGER", Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 37, null, vrm_, null); + data[0][i] = si; + ((SQLInteger)data[0][i]).set(i + 1); + }catch(Exception e){ + //should neve happen + + } + } + }else + { + data[0] = new Integer[contents.length]; + for (int i = 0; i < contents.length; i++) + { + try{ + data[0][i] = new Integer(i + 1); + }catch(Exception e){ + //should neve happen + + } + } + } + // initialize "VALUE" column + data[1] = contents; + contentTemplate_ = contentTemplate; + isSQLData_ = isSQLData; + + vrm_ = vrm; + con_ = con; + + String[] columnNames = new String[] { "INDEX", "VALUE" }; + + init ( CONCUR_READ_ONLY, TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.FETCH_FORWARD, 1, data, columnNames); + } + + /** + This method initializes this object. + + @param concurrency The concurrency of the resultset. + @param type The resultset type. + @param fetchDirection The Direction of the resultset. + @param fetchSize Size of fetch. + @param data Array of data objects + @param columnNames Names of columns. + **/ + void init ( int concurrency, int type, int fetchDirection, int fetchSize, + Object[][] data, String[] columnNames) + { + holdability_ = java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; + concurrency_ = concurrency; + fetchDirection_ = fetchDirection; + fetchSize_ = fetchSize; + type_ = type; //TYPE_SCROLL_INSENSITIVE + data_ = data; + numberOfColumns_ = data.length; + // if it's an empty result set, there will be zero columns + // and thus zero rows. + if (numberOfColumns_ > 0) numberOfRows_ = data[0].length; + + columnNameToIndexCache_ = new java.util.HashMap (); + for (int i = 0; i < columnNames.length; i++) + columnNameToIndexCache_.put (columnNames[i], new Integer (i + 1)); + + + openOnClient_ = true; + currentRowInRowset_ = -1; + + } + + /** + Closes this ResultSet + + @exception SQLException If an error occurs. + **/ + public void close () throws java.sql.SQLException + { + openOnClient_ = false; + } + + private java.util.Calendar getCalendar (java.util.TimeZone timeZone) + { + calendar_ = (calendar_ != null) ? calendar_ : new java.util.GregorianCalendar (); + calendar_.setTimeZone (timeZone); + return calendar_; + } + + private final void checkThatResultSetTypeIsScrollable () throws java.sql.SQLException + { + if (type_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) + JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID); + } + + // ---------------------- cursor position methods ---------------------- + + /** + Indicates if the cursor is positioned before the first row. + + @return true if the cursor is positioned before the first row; + false if the cursor is not positioned before the first + row or if the result set contains no rows. + + @exception SQLException If the result set is not open. + **/ + public boolean isBeforeFirst () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + boolean result = (currentRowInRowset_ == -1); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "isBeforeFirst"); + return result; + } + + /** + Indicates if the cursor is positioned after the last row. + + @return true if the cursor is positioned after the last row; + false if the cursor is not positioned after the last + row or if the result set contains no rows. + + @exception SQLException If the result set is not open. + **/ + public boolean isAfterLast () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + boolean result = (currentRowInRowset_ == numberOfRows_); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "isAfterLast"); + return result; + } + + /** + Indicates if the cursor is positioned on the first row. + + @return true if the cursor is positioned on the first row; + false if the cursor is not positioned on the first + row or the row number can not be determined. + + @exception SQLException If the result set is not open. + **/ + public boolean isFirst () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + boolean result = (currentRowInRowset_ == 0); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "isFirst"); + return result; + } + + /** + Indicates if the cursor is positioned on the last row. + + @return true if the cursor is positioned on the last row; + false if the cursor is not positioned on the last + row or the row number can not be determined. + + @exception SQLException If the result set is not open. + **/ + public boolean isLast () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + boolean result = (currentRowInRowset_ == (numberOfRows_ - 1)); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "isLast"); + return result; + } + + /** + Sets cursor position before the first row. + + @exception SQLException If the result set is not open. + **/ + public void beforeFirst () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "beforeFirst"); + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + currentRowInRowset_ = -1; + } + + /** + Positions the cursor after the last row. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + or an error occurs. + **/ + public void afterLast () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "afterLast"); + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + currentRowInRowset_ = numberOfRows_; + } + + /** + Positions the cursor to the first row. + + @return true if the requested cursor position is + valid; false otherwise. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + or an error occurs. + **/ + public boolean first () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + if (numberOfRows_ == 0) + isValidCursorPosition = false; + else { + isValidCursorPosition = true; + currentRowInRowset_ = 0; + } + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "first"); + return isValidCursorPosition; + } + + /** + Positions the cursor to the last row. + + @return true if the requested cursor position is + valid; false otherwise. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + or an error occurs. + **/ + public boolean last () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + if (numberOfRows_ == 0) + isValidCursorPosition = false; + else { + isValidCursorPosition = true; + currentRowInRowset_ = numberOfRows_ - 1; + } + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "last"); + return isValidCursorPosition; + } + + /** + Positions the cursor to the previous row. + + @return true if the requested cursor position is + valid; false otherwise. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + or an error occurs. + **/ + public boolean previous () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + currentRowInRowset_--; + if (currentRowInRowset_ >= 0) + isValidCursorPosition = true; + else { + isValidCursorPosition = false; + currentRowInRowset_ = -1; + } + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "previous"); + return isValidCursorPosition; + } + + /** + Positions the cursor to the next row. + + @return true if the requested cursor position is valid; false + if there are no more rows. + + @exception SQLException If the result set is not open, + or an error occurs. + **/ + public boolean next () throws java.sql.SQLException + { + checkForClosedResultSet (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + currentRowInRowset_++; + if (currentRowInRowset_ <= (numberOfRows_ - 1)) + isValidCursorPosition = true; + else { + isValidCursorPosition = false; + currentRowInRowset_ = numberOfRows_; + } + if (!isValidCursorPosition && type_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) + close (); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "next"); + return isValidCursorPosition; + } + + /** + Positions the cursor to an absolute row number. + + @param row The absolute row number. If the absolute row + number is positive, this positions the cursor + with respect to the beginning of the result set. + If the absolute row number is negative, this + positions the cursor with respect to the end + of result set. + @return true if the requested cursor position is + valid; false otherwise. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + the row number is 0, + or an error occurs. + */ + public boolean absolute (int row) throws java.sql.SQLException + { + //if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "absolute " + row); + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + + if (row >= 0) + currentRowInRowset_ = row - 1; + else + currentRowInRowset_ = row + numberOfRows_; + + if (currentRowInRowset_ >= 0 && currentRowInRowset_ <= (numberOfRows_ - 1)) + isValidCursorPosition = true; + else { + isValidCursorPosition = false; + if (currentRowInRowset_ < 0) + currentRowInRowset_ = -1; + else + currentRowInRowset_ = numberOfRows_; + } + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "absolute"); + return isValidCursorPosition; + } + + /** + Positions the cursor to a relative row number. + +

Attempting to move beyond the first row positions the + cursor before the first row. Attempting to move beyond the last + row positions the cursor after the last row. + + @param rows The relative row number. If the relative row + number is positive, this positions the cursor + after the current position. If the relative + row number is negative, this positions the + cursor before the current position. If the + relative row number is 0, then the cursor + position does not change. + @return true if the requested cursor position is + valid, false otherwise. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + the cursor is not positioned on a valid row, + or an error occurs. + */ + public boolean relative (int rows) throws java.sql.SQLException + { + //if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "relative", rows); + checkForClosedResultSet (); + checkThatResultSetTypeIsScrollable (); + wasNull_ = WAS_NULL_UNSET; + boolean isValidCursorPosition; + currentRowInRowset_ += rows; + + if (currentRowInRowset_ >= 0 && currentRowInRowset_ <= (numberOfRows_ - 1)) + isValidCursorPosition = true; + else { + isValidCursorPosition = false; + if (currentRowInRowset_ < 0) + currentRowInRowset_ = -1; + else + currentRowInRowset_ = numberOfRows_; + } + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "relative"); + return isValidCursorPosition; + } + + // ---------------------- state getter and setter methods ---------------------- + + /** + Returns the result set concurrency. + + @return The result set concurrency. Valid values are: +

+ + + @exception SQLException If the result set is not open. + **/ + public int getConcurrency () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getConcurrency"); + checkForClosedResultSet (); + return concurrency_; + } + + /** + Returns the result set type. + + @return The result set type. Valid values are: + + + + @exception SQLException If the result set is not open. + **/ + public int getType () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getType"); + checkForClosedResultSet (); + return type_; + } + + /** + Returns the fetch direction. + + @return The fetch direction. + Valid values are: + + + @exception SQLException If the result is not open. + **/ + public int getFetchDirection () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getFetchDirection"); + checkForClosedResultSet (); + return fetchDirection_; + } + + /** + Sets the direction in which the rows in a result set are + processed. + + @param direction The fetch direction for processing rows. + Valid values are: + + The default is the statement's fetch + direction. + + @exception SQLException If the result set is not open, + the result set is scrollable + and the input value is not + ResultSet.FETCH_FORWARD, + or the input value is not valid. + **/ + public void setFetchDirection (int direction) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "setFetchDirection"); + checkForClosedResultSet (); + switch (direction) { + case java.sql.ResultSet.FETCH_FORWARD: + case java.sql.ResultSet.FETCH_REVERSE: + case java.sql.ResultSet.FETCH_UNKNOWN: + fetchDirection_ = direction; + break; + default: + JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + } + + /** + Returns the fetch size. + + @return The fetch size. + + @exception SQLException If the result is not open. + **/ + public int getFetchSize () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getFetchSize"); + checkForClosedResultSet (); + return fetchSize_; + } + + /** + Sets the number of rows to be fetched from the database when more + rows are needed. This may be changed at any time. If the value + specified is zero, then the driver will choose an appropriate + fetch size. + + + @param rows The number of rows. This must be greater than + or equal to 0 and less than or equal to the + maximum rows limit. The default is the + statement's fetch size. + + @exception SQLException If the result set is not open + or the input value is not valid. + **/ + public void setFetchSize (int rows) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "setFetchSize"); + checkForClosedResultSet (); + if (rows < 0) + JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + fetchSize_ = rows; + } + + /** + Returns the name of the SQL cursor in use by the result set. + + @return The cursor name. + + @exception SQLException If the result is not open. + **/ + public String getCursorName () throws java.sql.SQLException + { + String cursorName = null; + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getCursorName"); + checkForClosedResultSet (); + return cursorName; + } + + /** + Returns the ResultSetMetaData object that describes the + result set's columns. ResultSetMetadata on Array columns is not supported and the + getMetaData method will return null. + + @return The metadata object. + + @exception SQLException If an error occurs. + **/ + public java.sql.ResultSetMetaData getMetaData () throws java.sql.SQLException + { + java.sql.ResultSetMetaData metaData = null;//new AS400JDBCResultSetMetaData ("", 2, "", new JDSimpleRow(new String[0], new SQLData[0], new int[0]), null, null, null); //@arrmd + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getMetaData"); + checkForClosedResultSet (); + return metaData; + } + + /** + Returns the statement for this result set. + + @return The statement for this result set, or null if the + result set was returned by a DatabaseMetaData + catalog method. + + @exception SQLException If an error occurs. + **/ + public java.sql.Statement getStatement () throws java.sql.SQLException + { + java.sql.Statement statement = null; + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getStatement"); + checkForClosedResultSet (); + return statement; + } + + /** + Returns the first warning reported for the result set. + Subsequent warnings may be chained to this warning. + + @return The first warning or null if no warnings + have been reported. + + @exception SQLException If an error occurs. + **/ + public java.sql.SQLWarning getWarnings () throws java.sql.SQLException + { + java.sql.SQLWarning warnings = null; + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getWarnings"); + checkForClosedResultSet (); + return warnings; + } + + /** + Clears all warnings that have been reported for the result set. + After this call, getWarnings() returns null until a new warning + is reported for the result set. + + @exception SQLException If an error occurs. + **/ + public void clearWarnings () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "clearWarnings"); + checkForClosedResultSet (); + } + + /** + Returns the column index for the specified column name. + + @param columnName The column name. + @return The column index (1-based). + + @exception SQLException If the result set is not open + or the column name is not found. + **/ + public int findColumn (String columnName) throws java.sql.SQLException + { + //if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "findColumn", columnName); + checkForClosedResultSet (); + int column = findColumnX (columnName); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "findColumn"); + return column; + } + + private final int findColumnX (String columnName) throws java.sql.SQLException + { + Integer index = (Integer) columnNameToIndexCache_.get (columnName.toUpperCase ()); + if (index != null) + return index.intValue (); + else + { + JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); + return -1;//never happens + } + + } + + /** + Retrieves the current row number. The first row is number 1, the second number 2, and so on. + + @return The current row number (1-based), or 0 if the current row + is not valid. + + @exception SQLException If the result set is not open. + **/ + public int getRow () throws java.sql.SQLException + { + checkForClosedResultSet (); + int row; + if (currentRowInRowset_ >= 0 && currentRowInRowset_ <= (numberOfRows_ - 1)) + row = currentRowInRowset_ + 1; + else + row = 0; + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getRow"); + return row; + } + + /** + Indicates if the last column read has the value of SQL NULL. + + @return true if the value is SQL NULL; + false otherwise. + + @exception SQLException If the result set is not open. + **/ + public boolean wasNull () throws java.sql.SQLException + { + checkForClosedResultSet (); + if (wasNull_ == WAS_NULL_UNSET) + JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID); + boolean result = (wasNull_ == WAS_NULL); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "wasNull"); + return result; + } + + // ---------------------- get on column methods ---------------------- + /** + Returns the value of a column as a Java boolean value. + + @param column The column name. + @return The column value or false if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public boolean getBoolean (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + + Object[] columnData = data_[column - 1]; + boolean result = false; //@nulllocalarrelem + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getBoolean(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getBoolean(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBoolean"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java boolean value. + + @param columnName The column name. + @return The column value or false if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public boolean getBoolean (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBoolean"); + return getBoolean (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java byte value. + + @param column The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public byte getByte (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + Object[] columnData = data_[column - 1]; + + byte result = 0; + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getByte(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getByte(); + } + } + + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getByte"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java byte value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public byte getByte (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getByte"); + return getByte (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java short value. + + @param column The column index (1-based). + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public short getShort (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + short result = 0; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getShort(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getShort(); + } + } + + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getShort"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java short value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public short getShort (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getShort"); + return getShort (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java int value. + + @param column The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column name is not found, or the + requested conversion is not valid. + **/ + public int getInt (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + int result = 0; //@nulllocalarrelem + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getInt(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getInt(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getInt"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java int value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column name is not found, or the + requested conversion is not valid. + **/ + public int getInt (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getInt"); + return getInt (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java long value. + + @param column The column index (1-based). + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public long getLong (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + long result = 0; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getLong(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getLong(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getLong"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java long value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public long getLong (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getLong"); + return getLong (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java float value. + + @param column The column index (1-based). + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public float getFloat (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + float result = 0; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getFloat(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getFloat(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getFloat"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java float value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public float getFloat (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getFloat"); + return getFloat (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java double value. + + @param column The column index (1-based). + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column name is not found, or the + requested conversion is not valid. + **/ + public double getDouble (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + double result = 0; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getDouble(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getDouble(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDouble"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java double value. + + @param columnName The column name. + @return The column value or 0 if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column name is not found, or the + requested conversion is not valid. + **/ + public double getDouble (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDouble"); + return getDouble (findColumnX (columnName)); + } + + /** + Returns the value of a column as a BigDecimal object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public java.math.BigDecimal getBigDecimal (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.math.BigDecimal result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getBigDecimal(-1); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getBigDecimal(-1); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBigDecimal"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a BigDecimal object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public java.math.BigDecimal getBigDecimal (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBigDecimal"); + return getBigDecimal (findColumnX (columnName)); + } + + /** + Returns the value of a column as a BigDecimal object. + + @param column The column index (1-based). + @param scale The number of digits after the decimal. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the scale is not valid, or the + requested conversion is not valid. + + @deprecated Use getBigDecimal(int) instead. + @see #getBigDecimal(int) + **/ + public java.math.BigDecimal getBigDecimal (int column, int scale) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBigDecimal " + column + " " + scale); + return getBigDecimal (column).setScale (scale); + } + + /** + Returns the value of a column as a BigDecimal object. + + @param columnName The column name. + @param scale The number of digits after the decimal. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the scale is not valid, or the + requested conversion is not valid. + + @deprecated Use getBigDecimal(int) instead. + @see #getBigDecimal(int) + **/ + public java.math.BigDecimal getBigDecimal (String columnName, int scale) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBigDecimal " + columnName + " " + scale); + return getBigDecimal (findColumnX (columnName), scale); + } + + /** + Returns the value of a column as a java.sql.Date object using + the default calendar. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Date getDate (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDate"); + return getDateX (column, java.util.TimeZone.getDefault ()); + } + + /** + Returns the value of a column as a java.sql.Date object using + the default calendar. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Date getDate (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDate"); + return getDate (findColumnX (columnName)); + } + + /** + Returns the value of a column as a java.sql.Time object using the + default calendar. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Time getTime (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTime"); + return getTimeX (column, java.util.TimeZone.getDefault ()); + } + + /** + Returns the value of a column as a java.sql.Time object using the + default calendar. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Time getTime (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTime"); + return getTime (findColumnX (columnName)); + } + + /** + Returns the value of a column as a java.sql.Timestamp object + using the default calendar. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Timestamp getTimestamp (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTimestamp"); + return getTimestampX (column, java.util.TimeZone.getDefault ()); + } + + /** + Returns the value of a column as a java.sql.Timestamp object + using the default calendar. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Timestamp getTimestamp (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTimestamp"); + return getTimestamp (findColumnX (columnName)); + } + + /** + Returns the value of a column as a java.sql.Date object using + a calendar other than the default. + + @param column The column index (1-based). + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the calendar is null, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Date getDate (int column, java.util.Calendar calendar) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDate " + column ); + + java.sql.Date result = getDateX (column, calendar.getTimeZone ()); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDate"); + return result; + } + + /** + Returns the value of a column as a java.sql.Date object using + a calendar other than the default. + + @param columnName The column name. + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the calendar is null, or the + requested conversion is not valid. + **/ + public java.sql.Date getDate (String columnName, java.util.Calendar calendar) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getDate " + columnName ); + return getDate (findColumnX (columnName), calendar); + } + + private java.sql.Date getDateX (int column, java.util.TimeZone timeZone) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.sql.Date date = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + date = ((SQLData)columnData[currentRowInRowset_]).getDate(getCalendar(timeZone)); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], getCalendar(timeZone), -1); + date = contentTemplate_.getDate(getCalendar(timeZone)); + } + } + + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return date; + } + + /** + Returns the value of a column as a java.sql.Time object using the + default calendar. + + @param column The column index (1-based). + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Time getTime (int column, java.util.Calendar calendar) throws java.sql.SQLException + { + java.sql.Time result = getTimeX (column, calendar.getTimeZone ()); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTime"); + return result; + } + + /** + Returns the value of a column as a java.sql.Time object using the + default calendar. + + @param columnName The column name. + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Time getTime (String columnName, java.util.Calendar calendar) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTime"); + return getTime (findColumnX (columnName), calendar); + } + + private java.sql.Time getTimeX (int column, java.util.TimeZone timeZone) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.sql.Time time = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + time = ((SQLData)columnData[currentRowInRowset_]).getTime(getCalendar(timeZone)); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], getCalendar(timeZone), -1); + time = contentTemplate_.getTime(getCalendar(timeZone)); + } + } + + + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return time; + } + + /** + Returns the value of a column as a java.sql.Timestamp object + using a calendar other than the default. + + @param column The column index (1-based). + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the calendar is null, or the + requested conversion is not valid. + **/ + synchronized public java.sql.Timestamp getTimestamp (int column, java.util.Calendar calendar) throws java.sql.SQLException + { + java.sql.Timestamp result = getTimestampX (column, calendar.getTimeZone ()); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTimestamp"); + return result; + } + + /** + Returns the value of a column as a java.sql.Timestamp object + using a calendar other than the default. + + @param columnName The column name. + @param calendar The calendar. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the calendar is null, or the + requested conversion is not valid. + **/ + public java.sql.Timestamp getTimestamp (String columnName, java.util.Calendar calendar) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getTimestamp"); + return getTimestamp (findColumnX (columnName), calendar); + } + + private java.sql.Timestamp getTimestampX (int column, java.util.TimeZone timeZone) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.sql.Timestamp timestamp = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + timestamp = ((SQLData)columnData[currentRowInRowset_]).getTimestamp(getCalendar(timeZone)); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], getCalendar(timeZone), -1); + timestamp = contentTemplate_.getTimestamp(getCalendar(timeZone)); + } + } + + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return timestamp; + } + + /** + Returns the value of a column as a Java byte array. + +

This can also be used to get values from columns + with other types. The values are returned in their + native IBM i format. This is not supported for + result sets returned by a DatabaseMetaData object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public byte[] getBytes (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + byte[] result = null; + Object[] columnData = data_[column - 1]; + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getBytes(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getBytes(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBytes"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java byte array. + +

This can also be used to get values from columns + with other types. The values are returned in their + native IBM i format. This is not supported for + result sets returned by a DatabaseMetaData object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public byte[] getBytes (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBytes"); + return getBytes (findColumnX (columnName)); + } + + /** + Returns the value of a column as a String object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + synchronized public String getString (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + String result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getString(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getString(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getString"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a String object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public String getString (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getString"); + return getString (findColumnX (columnName)); + } + + /** + Returns the value of a column as a stream of uninterpreted + bytes. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.io.InputStream getBinaryStream (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.io.InputStream result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getBinaryStream(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getBinaryStream(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBinaryStream"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a stream of uninterpreted + bytes. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.io.InputStream getBinaryStream (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBinaryStream"); + return getBinaryStream (findColumnX (columnName)); + } + + /** + Returns the value of a column as a stream of ASCII + characters. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public java.io.InputStream getAsciiStream (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.io.InputStream result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getAsciiStream(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getAsciiStream(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getAsciiStream"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + + /** + Returns the value of a column as a stream of ASCII + characters. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public java.io.InputStream getAsciiStream (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getAsciiStream"); + return getAsciiStream (findColumnX (columnName)); + } + + + /** + Returns the value of a column as a stream of Unicode + characters. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + + @deprecated Use getCharacterStream(int) instead. + @see #getCharacterStream(int) + **/ + public java.io.InputStream getUnicodeStream (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.io.InputStream result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getUnicodeStream(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getUnicodeStream(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getUnicodeStream"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a stream of Unicode + characters. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + + @deprecated Use getCharacterStream(String) instead. + @see #getCharacterStream(String) + **/ + public java.io.InputStream getUnicodeStream (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getUnicodeStream"); + return getUnicodeStream (findColumnX (columnName)); + } + + /** + Returns the value of a column as a character stream. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + */ + public java.io.Reader getCharacterStream (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.io.Reader result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + result = ((SQLData)columnData[currentRowInRowset_]).getCharacterStream(); + } + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getCharacterStream(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getCharacterStream"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a character stream. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + */ + public java.io.Reader getCharacterStream (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getCharacterStream"); + return getCharacterStream (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Blob object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Blob getBlob (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + java.sql.Blob result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getBlob(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getBlob(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBlob"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Blob object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Blob getBlob (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getBlob"); + return getBlob (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Clob object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Clob getClob (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.sql.Clob result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getClob(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getClob(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getClob"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Clob object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public java.sql.Clob getClob (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getClob"); + return getClob (findColumnX (columnName)); + } + + /** + Returns the value of a column as an Array object. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException + **/ + public java.sql.Array getArray (int column) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + /** + Returns the value of a column as an Array object. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException + **/ + public java.sql.Array getArray (String columnName) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + /** + Returns the value of a column as a Ref object. + DB2 for IBM i does not support structured types. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException Always thrown because DB2 for IBM i does not support structured types. + **/ + public java.sql.Ref getRef (int column) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + /** + Returns the value of a column as a Ref object. + DB2 for IBM i does not support structured types. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException Always thrown because DB2 for IBM i does not support structured types. + **/ + public java.sql.Ref getRef (String columnName) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + /** + Returns the value of an SQL DATALINK output parameter as a + java.net.URL object. + + @param column The column index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed or + the requested conversion is not valid. + **/ + public java.net.URL getURL (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.net.URL result = null; + Object[] columnData = data_[column - 1]; + String stringResult = null; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + stringResult = ((SQLData)columnData[currentRowInRowset_]).getString(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + stringResult = contentTemplate_.getString(); + } + } + + try + { + if(stringResult == null) + result = null; + else + result = new java.net.URL(stringResult); + } + catch(MalformedURLException e) + { + JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID, e); + result = null; + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getURL"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of an SQL DATALINK output parameter as a + java.net.URL object. + + @param columnName The column name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed or + the requested conversion is not valid. + **/ + public java.net.URL getURL (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getURL"); + return getURL (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java Object. + This can be used to get values from columns with all + SQL types. + + @param column The column index (1-based). + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public Object getObject (int column) throws java.sql.SQLException + { + checkGetterPreconditions (column); + Object[] columnData = data_[column - 1]; + Object result = null; + + if(isSQLData_) + { + + if(columnData[currentRowInRowset_] != null) //@nullelem + result = ((SQLData)columnData[currentRowInRowset_]).getObject(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getObject(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getObject"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + Returns the value of a column as a Java Object. + This can be used to get values from columns with all + SQL types. + + @param columnName The column name. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public Object getObject (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getObject"); + return getObject (findColumnX (columnName)); + } + + /** + Returns the value of a column as a Java Object. + + @param column The column index (1-based). + @param map The type map. This is not used. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the type map is null, or the + requested conversion is not valid. + **/ + public Object getObject (int column, java.util.Map map) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + /** + Returns the value of a column as a Java Object. + + @param columnName The column name. + @param map The type map. This is not used. + @return The column value or null if the value is SQL NULL. + + @exception SQLException If the result set is not open, + the cursor is not positioned on a row, + the column index is not valid, + the type map is null, or the + requested conversion is not valid. + **/ + public Object getObject (String columnName, java.util.Map map) throws java.sql.SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + // ---------------------- update on column methods ---------------------- + + /** + Updates a column in the current row using SQL NULL. + + @param column The column index (1-based). + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateNull (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNull"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using SQL NULL. + + @param columnName The column name. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateNull (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNull"); + updateNull (findColumnX (columnName)); + } + + /** + Updates a column in the current row using a Java byte value. + The driver converts this to an SQL SMALLINT value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateByte (int column, byte x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateByte"); + checkUpdatePreconditions (column); + } + + + /** + Updates a column in the current row using a Java byte value. + The driver converts this to an SQL SMALLINT value. + + @param columnName The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateByte (String columnName, byte x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateByte"); + updateByte (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java boolean value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBoolean (int column, boolean x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBoolean"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java boolean value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBoolean (String columnName, boolean x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBoolean"); + updateBoolean (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java short value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateShort (int column, short x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateShort"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java short value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateShort (String columnName, short x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateShort"); + updateShort (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java int value. + The driver converts this to an SQL INTEGER value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateInt (int column, int x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateInt"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java int value. + The driver converts this to an SQL INTEGER value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateInt (String columnName, int x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateInt"); + updateInt (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java long value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateLong (int column, long x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateLong"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java long value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateLong (String columnName, long x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateLong"); + updateLong (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java float value. + The driver converts this to an SQL REAL value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateFloat (int column, float x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateFloat"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java float value. + The driver converts this to an SQL REAL value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateFloat (String columnName, float x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateFloat"); + updateFloat (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java double value. + The driver converts this to an SQL DOUBLE value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateDouble (int column, double x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateDouble"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java double value. + The driver converts this to an SQL DOUBLE value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateDouble (String columnName, double x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateDouble"); + updateDouble (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a BigDecimal value. The + driver converts this to an SQL NUMERIC value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBigDecimal (int column, java.math.BigDecimal x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBigDecimal"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a BigDecimal value. The + driver converts this to an SQL NUMERIC value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBigDecimal (String columnName, java.math.BigDecimal x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBigDecimal"); + updateBigDecimal (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a java.sql.Date value. + The driver converts this to an SQL DATE value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateDate (int column, java.sql.Date x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateDate"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a java.sql.Date value. + The driver converts this to an SQL DATE value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateDate (String columnName, java.sql.Date x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateDate"); + updateDate (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a java.sql.Time value. + The driver converts this to an SQL TIME value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateTime (int column, java.sql.Time x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateTime"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a java.sql.Time value. + The driver converts this to an SQL TIME value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateTime (String columnName, java.sql.Time x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateTime"); + updateTime (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a java.sql.Timestamp value. + The driver converts this to an SQL TIMESTAMP value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateTimestamp (int column, java.sql.Timestamp x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateTimestamp"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a java.sql.Timestamp value. + The driver converts this to an SQL TIMESTAMP value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateTimestamp (String columnName, java.sql.Timestamp x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateTimestamp"); + updateTimestamp (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java byte array value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBytes (int column, byte x[]) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBytes"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java byte array value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBytes (String columnName, byte x[]) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBytes"); + updateBytes (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a String value. + The driver converts this to an SQL VARCHAR value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateString (int column, String x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateString"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a String value. + The driver converts this to an SQL VARCHAR value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateString (String columnName, String x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateString"); + updateString (findColumnX (columnName), x); + } + + /** + * Updates the designated column with a binary stream value, which will have + * the specified number of bytes. + * @param column column index + * @param x the new column value + * @param length the length of the stream + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (int column, java.io.InputStream x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a binary stream value, which will have + * the specified number of bytes. + * @param columnName column index + * @param x the new column value + * @param length the length of the stream + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (String columnName, java.io.InputStream x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + updateBinaryStream (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + * @param column + * @param x the new column value + * @param length the length of the stream + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateAsciiStream (int column, java.io.InputStream x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + checkUpdatePreconditions (column); + } + + + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + * @param columnName + * @param x the new column value + * @param length the length of the stream + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateAsciiStream (String columnName, java.io.InputStream x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + updateAsciiStream (findColumnX (columnName), x, length); + } + + /** + Updates a column in the current row using a Reader value. + The driver reads the data from the Reader as needed until no more + characters are available. The driver converts this to an SQL VARCHAR + value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + @param length The length. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid, + the length is not valid, or an error + happens while reading the input stream. + **/ + public void updateCharacterStream (int column, java.io.Reader x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Reader value. + The driver reads the data from the Reader as needed until no more + characters are available. The driver converts this to an SQL VARCHAR + value. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + @param length The length. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid, + the length is not valid, or an error + happens while reading the input stream. + **/ + public void updateCharacterStream (String columnName, java.io.Reader x, int length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream"); + updateCharacterStream (findColumnX (columnName), x, length); + } + + /** + Updates a column in the current row using a Java Blob value. + The driver converts this to an SQL BLOB value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBlob (int column, java.sql.Blob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java Blob value. + The driver converts this to an SQL BLOB value. + + @param columnName The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateBlob (String columnName, java.sql.Blob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob"); + updateBlob (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using a Java Clob value. + The driver converts this to an SQL CLOB value. + + @param column The column index (1-based). + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateClob (int column, java.sql.Clob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using a Java Clob value. + The driver converts this to an SQL CLOB value. + + @param columnName The column name. + @param x The column value. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, or the + requested conversion is not valid. + **/ + public void updateClob (String columnName, java.sql.Clob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + updateClob (findColumnX (columnName), x); + } + + /** + Updates the value of a column as an Array object. + + @param column The column index (1-based). + @param x The column value or null if the value is SQL NULL. + + @exception SQLException + **/ + public void updateArray (int column, java.sql.Array x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateArray"); + checkUpdatePreconditions (column); + } + + /** + Updates the value of a column as an Array object. + + @param columnName The column index (1-based). + @param x The column value or null if the value is SQL NULL. + + @exception SQLException + **/ + public void updateArray (String columnName, java.sql.Array x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateArray"); + updateArray (findColumnX (columnName), x); + } + + /** + Updates the value of an SQL REF output parameter as a Ref value. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException + **/ + public void updateRef (int column, java.sql.Ref x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateRef"); + checkUpdatePreconditions (column); + } + + /** + Updates the value of an SQL REF output parameter as a Ref value. + + @param columnName The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException + **/ + public void updateRef (String columnName, java.sql.Ref x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateRef"); + updateRef (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using an Object value. + The driver converts this to a value of an SQL type, depending on + the type of the specified value. The JDBC specification defines + a standard mapping from Java types to SQL types. + + @param column The column index (1-based). + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateObject (int column, Object x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateObject"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using an Object value. + The driver converts this to a value of an SQL type, depending on + the type of the specified value. The JDBC specification defines + a standard mapping from Java types to SQL types. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateObject (String columnName, Object x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateObject"); + updateObject (findColumnX (columnName), x); + } + + /** + Updates a column in the current row using an Object value. + The driver converts this to a value of an SQL type, depending on + the type of the specified value. The JDBC specification defines + a standard mapping from Java types to SQL types. + + @param column The column index. + @param x The column value or null to update + the value to SQL NULL. + @param scale The scale. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateObject (int column, Object x, int scale) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateObject"); + checkUpdatePreconditions (column); + } + + /** + Updates a column in the current row using an Object value. + The driver converts this to a value of an SQL type, depending on + the type of the specified value. The JDBC specification defines + a standard mapping from Java types to SQL types. + + @param columnName The column name. + @param x The column value or null to update + the value to SQL NULL. + @param scale The scale. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the column index is not valid, + or the requested conversion is not valid. + **/ + public void updateObject (String columnName, Object x, int scale) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateObject"); + updateObject (findColumnX (columnName), x, scale); + } + + /** + Indicates if the current row has been updated. This driver does + not support this method. + + @return Always false. + + @exception SQLException If an error occurs. + **/ + public boolean rowUpdated () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return false; + } + + /** + Indicates if the current row has been inserted. This driver does + not support this method. + + @return Always false. + + @exception SQLException If an error occurs. + **/ + public boolean rowInserted () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"rowInserted()"); + return false; + } + + /** + Indicates if the current row has been deleted. A result set + of type TYPE_SCROLL_INSENSITIVE may contain rows that have + been deleted. + + @return true if current row has been deleted; false otherwise. + + @exception SQLException If an error occurs. + **/ + public boolean rowDeleted () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"rowDeleted()"); + return false; + } + + /** + Inserts the contents of the insert row into the result set + and the database. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on the insert row, + a column that is not nullable was not specified, + or an error occurs. + **/ + public void insertRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"insertRow"); + + } + + /** + Cancels all pending updates that have been made since the last + call to updateRow(). + + @exception SQLException If the result set is not open + or the result set is not updatable. + **/ + public void updateRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"updateRow()"); + } + + /** + Deletes the current row from the result set and the database. + After deleting a row, the cursor position is no longer valid, + so it must be explicitly repositioned. + + @exception SQLException If the result set is not open, + the result set is not updatable, + the cursor is not positioned on a row, + the cursor is positioned on the insert row, + or an error occurs. + **/ + public void deleteRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"deleteRow()"); + } + + /** + Refreshes the current row from the database. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + the cursor is not positioned on a row, + the cursor is positioned on the + insert row or an error occurs. + **/ + public void refreshRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"refreshRow()"); + } + + /** + Cancels all pending updates that have been made since the last + call to updateRow(). + + @exception SQLException If the result set is not open + or the result set is not updatable. + **/ + public void cancelRowUpdates () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"cancelRowUpdates()"); + } + + /** + Positions the cursor to the insert row. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + the result set is not updatable, + or an error occurs. + **/ + public void moveToInsertRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"moveToInsertRow()"); + } + + /** + Positions the cursor to the current row. + + @exception SQLException If the result set is not open, + the result set is not scrollable, + or an error occurs. + **/ + public void moveToCurrentRow () throws java.sql.SQLException + { + checkUpdatePreconditions (); + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED,"moveToCurrentRow()"); + } + + // ---------------------- condition checking helper methods ---------------------- + + private final void checkForClosedResultSet () throws java.sql.SQLException + { + if (!openOnClient_) + JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID); + } + + private final void checkForValidColumnIndex (int column) throws java.sql.SQLException + { + if (column < 1 || column > numberOfColumns_) + JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID); + } + + private final void checkForValidPosition () throws java.sql.SQLException + { + if (currentRowInRowset_ < 0 || currentRowInRowset_ > (numberOfRows_ - 1)) + JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID); + } + + private final void checkForConcurrency () throws java.sql.SQLException + { + if (concurrency_ != java.sql.ResultSet.CONCUR_UPDATABLE) + JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID); + } + + private final void checkGetterPreconditions (int column) throws java.sql.SQLException + { + checkForClosedResultSet (); + checkForValidColumnIndex (column); + checkForValidPosition (); + } + + private final void checkUpdatePreconditions (int column) throws java.sql.SQLException + { + checkForClosedResultSet (); + checkForValidColumnIndex (column); + checkForConcurrency (); + } + + private final void checkUpdatePreconditions () throws java.sql.SQLException + { + checkForClosedResultSet (); + checkForConcurrency (); + } + + // ---------- JDBC 4 methods ---------- + + /** + Indicates if the result set is closed. + + @return true if this result set is closed; + false otherwise. + **/ + public boolean isClosed () throws java.sql.SQLException + { + return !openOnClient_; + } + + /** + * Retrieves the holdability. + * @throws SQLException if a database error occurs + */ + public int getHoldability () throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getHoldability"); + checkForClosedResultSet (); + return holdability_; + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a + * java.io.Reader object. + * @return a java.io.Reader object that contains the column + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language. + * @param column + * @exception SQLException if a database access error occurs + */ + public java.io.Reader getNCharacterStream (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.io.Reader result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getNCharacterStream(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getNCharacterStream(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNCharacterStream"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a + * java.io.Reader object. + * @return a java.io.Reader object that contains the column + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language. + * @param columnName + * @exception SQLException if a database access error occurs + */ + public java.io.Reader getNCharacterStream (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNCharacterStream"); + return getNCharacterStream (findColumnX (columnName)); + } + + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a NClob object + * in the Java programming language. + * + * @param column + * @return a NClob object representing the SQL + * NCLOB value in the specified column + * @exception SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; or if a database access error occurss + */ +/* ifdef JDBC40 */ + public java.sql.NClob getNClob (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + java.sql.NClob result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getNClob(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getNClob(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNClob"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } +/* endif */ + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a NClob object + * in the Java programming language. + * + * @param columnName + * @return a NClob object representing the SQL + * NCLOB value in the specified column + * @exception SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; or if a database access error occurss + */ +/* ifdef JDBC40 */ + public java.sql.NClob getNClob (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNClob"); + return getNClob (findColumnX (columnName)); + } + +/* endif */ + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as + * a String in the Java programming language. + * It is intended for use when + * accessing NCHAR,NVARCHAR + * and LONGNVARCHAR columns. + * + * @param column + * @return the column value; if the value is SQL NULL, the + * value returned is null + * @exception SQLException if a database access error occurs + */ + public String getNString (int column) throws java.sql.SQLException + { + + checkGetterPreconditions (column); + String result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getNString(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getNString(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNString"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as + * a String in the Java programming language. + * It is intended for use when + * accessing NCHAR,NVARCHAR + * and LONGNVARCHAR columns. + * + * @param columnName + * @return the column value; if the value is SQL NULL, the + * value returned is null + * @exception SQLException if a database access error occurs + */ + public String getNString (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getNString"); + return getNString (findColumnX (columnName)); + } + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet object as a java.sql.RowId object in the Java + * programming language. + * + * @param column The column number + * @return the column value ; if the value is a SQL NULL the + * value returned is null + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + public java.sql.RowId getRowId (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getRowId"); + checkGetterPreconditions (column); + java.sql.RowId result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getRowId(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getRowId(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getRowId"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } +/* endif */ + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet object as a java.sql.RowId object in the Java + * programming language. + * + * @param columnName The column name + * @return the column value ; if the value is a SQL NULL the + * value returned is null + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + public java.sql.RowId getRowId (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getRowId"); + return getRowId (findColumnX (columnName)); + } +/* endif */ + + /** + * Retrieves the value of the designated column in the current row of + * this ResultSet as a + * java.sql.SQLXML object in the Java programming language. + * @param column + * @return a SQLXML object that maps an SQL XML value + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + public java.sql.SQLXML getSQLXML (int column) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getSQLXML"); + checkGetterPreconditions (column); + java.sql.SQLXML result = null; + Object[] columnData = data_[column - 1]; + + if(isSQLData_) + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + result = ((SQLData)columnData[currentRowInRowset_]).getSQLXML(); + } + else + { + if(columnData[currentRowInRowset_] != null) //@nulllocalarrelem + { + contentTemplate_.set(columnData[currentRowInRowset_], calendar_, -1); + result = contentTemplate_.getSQLXML(); + } + } + + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getSQLXML"); + wasNull_ = (columnData[currentRowInRowset_] == null) ? WAS_NULL : WAS_NOT_NULL; + return result; + } +/* endif */ + + /** + * Retrieves the value of the designated column in the current row of + * this ResultSet as a + * java.sql.SQLXML object in the Java programming language. + * @param columnName + * @return a SQLXML object that maps an SQL XML value + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + public java.sql.SQLXML getSQLXML (String columnName) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "getSQLXML"); + return getSQLXML (findColumnX (columnName)); + } +/* endif */ + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + + * @param column + * @param x the new column value + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateAsciiStream (int column, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + * @param columnName + * @param x the new column value + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateAsciiStream (String columnName, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + updateAsciiStream (findColumnX (columnName), x); + } + + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + * @param column + * @param x the new column value + * @param length + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateAsciiStream (int column, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with an ascii stream value, which will have + * the specified number of bytes. + * @param columnName + * @param x the new column value + * @param length + * @exception SQLException if a database access error occurs, + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateAsciiStream (String columnName, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateAsciiStream"); + updateAsciiStream (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column with a binary stream value. + * + * @param column + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (int column, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a binary stream value. + * + * @param columnName + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (String columnName, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + updateBinaryStream (findColumnX (columnName), x); + } + + /** + * Updates the designated column with a binary stream value. + * + * @param column + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (int column, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a binary stream value. + * + * @param columnName + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBinaryStream (String columnName, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBinaryStream"); + updateBinaryStream (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column using the given input stream. The data will be read from the stream + * as needed until end-of-stream is reached. + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @exception SQLException if the columnIndex is not valid; if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateBlob (int column, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given input stream. The data will be read from the stream + * as needed until end-of-stream is reached. + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @exception SQLException if the columnIndex is not valid; if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateBlob (String columnName, java.io.InputStream x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob" ); + updateBlob (findColumnX (columnName), x); + } + + /** + * Updates the designated column using the given input stream. The data will be read from the stream + * as needed until end-of-stream is reached. + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @param length + * @exception SQLException if the columnIndex is not valid; if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateBlob (int column, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob" ); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given input stream. The data will be read from the stream + * as needed until end-of-stream is reached. + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @param length + * @exception SQLException if the columnIndex is not valid; if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateBlob (String columnName, java.io.InputStream x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateBlob" ); + updateBlob (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column with a character stream value. + * + * @param column + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateCharacterStream (int column, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream" ); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a character stream value. + * + * @param columnName + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateCharacterStream (String columnName, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream" ); + updateCharacterStream (findColumnX (columnName), x); + } + + /** + * Updates the designated column with a character stream value. + * + * @param column + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateCharacterStream (int column, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a character stream value. + * + * @param columnName + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateCharacterStream (String columnName, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateCharacterStream"); + updateCharacterStream (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column using the given Reader + * object. + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateClob (int column, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given Reader + * object. + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateClob (String columnName, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + updateClob (findColumnX (columnName), x); + } + + /** + * Updates the designated column using the given Reader + * object. + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateClob (int column, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given Reader + * object. + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY + * or this method is called on a closed result set + */ + public void updateClob (String columnName, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateClob"); + updateClob (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column with a character stream value. + * + * @param column + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNCharacterStream (int column, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNCharacterStream"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a character stream value. + * + * @param columnName + * @param x the new column value + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNCharacterStream (String columnName, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNCharacterStream"); + updateNCharacterStream (findColumnX (columnName), x); + } + + /** + * Updates the designated column with a character stream value. + * + * @param column + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNCharacterStream (int column, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNCharacterStream"); + checkUpdatePreconditions (column); + } + + + /** + * Updates the designated column with a character stream value. + * + * @param columnName + * @param x the new column value + * @param length + * @exception SQLException if the columnIndex is not valid; + * if a database access error occurs; + * the result set concurrency is CONCUR_READ_ONLY or this method is called on a closed result set + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNCharacterStream (String columnName, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNCharacterStream" ); + updateNCharacterStream (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column using the given Reader + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public void updateNClob (int column, java.sql.NClob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob" ); + checkUpdatePreconditions (column); + } +/* endif */ + + /** + * Updates the designated column using the given Reader + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public void updateNClob (String columnName, java.sql.NClob x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob" ); + updateNClob (findColumnX (columnName), x); + } +/* endif */ + /** + * Updates the designated column using the given Reader + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNClob (int column, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob" ); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given Reader + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNClob (String columnName, java.io.Reader x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob" ); + updateNClob (findColumnX (columnName), x); + } + + /** + * Updates the designated column using the given Reader + * + * @param column + * @param x An object that contains the data to set the parameter value to. + * @param length + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNClob (int column, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob"); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column using the given Reader + * + * @param columnName + * @param x An object that contains the data to set the parameter value to. + * @param length + * @throws SQLException if the columnIndex is not valid; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; this method is called on a closed result set, + * if a database access error occurs or + * the result set concurrency is CONCUR_READ_ONLY + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void updateNClob (String columnName, java.io.Reader x, long length) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNClob"); + updateNClob (findColumnX (columnName), x, length); + } + + /** + * Updates the designated column with a String value. + * It is intended for use when updating NCHAR,NVARCHAR + * and LONGNVARCHAR columns. + * + * @param column + * @param x The value for the column to be updated + * @throws SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; or if a database access error occurs + */ + public void updateNString (int column, String x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNString" ); + checkUpdatePreconditions (column); + } + + /** + * Updates the designated column with a String value. + * It is intended for use when updating NCHAR,NVARCHAR + * and LONGNVARCHAR columns. + * + * @param columnName + * @param x The value for the column to be updated + * @throws SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; or if a database access error occurs + */ + public void updateNString (String columnName, String x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateNString" ); + updateNString (findColumnX (columnName), x); + } + + /** + * Updates the designated column with a RowId value. + * + * @param column + * @param x the column value + * @throws SQLException if a database access occurs + */ +/* ifdef JDBC40 */ + + public void updateRowId (int column, java.sql.RowId x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateRowId"); + checkUpdatePreconditions (column); + } +/* endif */ + /** + * Updates the designated column with a RowId value. + * + * @param columnName + * @param x the column value + * @throws SQLException if a database access occurs + */ +/* ifdef JDBC40 */ + public void updateRowId (String columnName, java.sql.RowId x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateRowId"); + updateRowId (findColumnX (columnName), x); + } +/* endif */ + /** + * Updates the designated column with a java.sql.SQLXML value. + * + * @param column + * @param x The value for the column to be updated + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + + public void updateSQLXML (int column, java.sql.SQLXML x) throws java.sql.SQLException + { + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateSQLXML"); + checkUpdatePreconditions (column); + } +/* endif */ + /** + * Updates the designated column with a java.sql.SQLXML value. + * + * @param columnName + * @param x The value for the column to be updated + * @throws SQLException if a database access error occurs + */ +/* ifdef JDBC40 */ + + public void updateSQLXML (String columnName, java.sql.SQLXML x) throws java.sql.SQLException + { + updateSQLXML (findColumnX (columnName), x); + if (JDTrace.isTraceOn()) JDTrace.logInformation(this, "updateSQLXML"); + } +/* endif */ + + + public Object getObject(int columnIndex, Class type) throws SQLException { + + // Throw exception if type is null + if (type == null) { + JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID); + } + if (byteArrayClass_ == null) { + byte[] byteArray = new byte[1]; + byteArrayClass_ = byteArray.getClass(); + } + // Use the appropriate method to get the correct data type. + // After checking for string, we check for classes in the + // order specified in Table B-6 of the JDBC 4.0 specification + // + if (type == java.lang.String.class ) { + return getString(columnIndex); + } else if (type == java.lang.Byte.class){ + byte b = getByte(columnIndex); + if (b == 0 && wasNull()) { + return null; + } else { + return new Byte(b); + } + } else if (type == java.lang.Short.class){ + short s = getShort(columnIndex); + if (s == 0 && wasNull()) { + return null; + } else { + return new Short(s); + } + } else if (type == java.lang.Integer.class){ + int i = getInt(columnIndex); + if (i == 0 && wasNull()) { + return null; + } else { + return new Integer(i); + } + } else if (type == java.lang.Long.class){ + long l = getLong(columnIndex); + if (l == 0 && wasNull()) { + return null; + } else { + return new Long(l); + } + } else if (type == java.lang.Float.class){ + float f = getFloat(columnIndex); + if (f == 0 && wasNull()) { + return null; + } else { + return new Float(f); + } + } else if (type == java.lang.Double.class){ + double d = getDouble(columnIndex); + if (d == 0 && wasNull()) { + return null; + } else { + return new Double(d); + } + } else if (type == java.math.BigDecimal.class){ + return getBigDecimal(columnIndex); + } else if (type == java.lang.Boolean.class) { + boolean b = getBoolean(columnIndex); + if (b == false && wasNull()) { + return null; + } else { + return new Boolean (b); + } + + } else if (type == java.sql.Date.class){ + return getDate(columnIndex); + } else if (type == java.sql.Time.class){ + return getTime(columnIndex); + } else if (type == java.sql.Timestamp.class){ + return getTimestamp(columnIndex); + } else if (type == byteArrayClass_){ + return getBytes(columnIndex); + } else if (type == InputStream.class){ + return getBinaryStream(columnIndex); + } else if (type == Reader.class){ + return getCharacterStream(columnIndex); + } else if (type == Clob.class){ + return getClob(columnIndex); + } else if (type == Blob.class){ + return getBlob(columnIndex); + } else if (type == Array.class){ + return getArray(columnIndex); + } else if (type == Ref.class){ + return getRef(columnIndex); + } else if (type == URL.class){ + return getURL(columnIndex); +/* ifdef JDBC40 */ + } else if (type == NClob.class){ + return getNClob(columnIndex); + } else if (type == RowId.class){ + return getRowId(columnIndex); + } else if (type == SQLXML.class){ + return getSQLXML(columnIndex); +/* endif */ + } else if (type == Object.class){ + return getObject(columnIndex); + } + + JDError.throwSQLException (JDError.EXC_DATA_TYPE_INVALID); + return null; + + + + } + + + public Object getObject(String columnLabel, Class type) + throws SQLException { + + return getObject(findColumnX (columnLabel), type); + } + + + protected String[] getValidWrappedList() + { + return new String[] { "com.ibm.as400.access.AS400JDBCArrayResultSet", "java.sql.ResultSet" }; + } + + + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCBlob.java b/jdbc40/com/ibm/as400/access/AS400JDBCBlob.java new file mode 100644 index 000000000..79217cfff --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCBlob.java @@ -0,0 +1,429 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCBlob.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; + +// Note: This code in this class requires understanding of bit manipulation +// and sign extension. Do not attempt to rework this code if you do not +// have a grasp of these concepts. + +// Currently, the database host server only supports 2 GB LOBs. Therefore, +// we validate any long parameters to make sure they are not greater than +// the maximum positive value for a 4-byte int (2 GB). This has the added +// bonus of being able to cast the long down to an int without worrying +// about sign extension. There are some cases where we could allow the +// user to pass in a long greater than 2 GB, but for consistency, we will +// throw an exception. + +// Offset refers to a 0-based index. Position refers to a 1-based index. + + +/** + * The AS400JDBCBlob class provides access to binary large + * objects. The data is valid only within the current + * transaction. +**/ +public class AS400JDBCBlob implements Blob +{ + static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others."; + + private byte[] data_; + private int maxLength_; + static final int MAX_LOB_SIZE = 2147483647; //@PDA jdbc40 - same as native driver + +/** +Constructs an AS400JDBCBlob object. The data is contained +in the raw byte array. No further communication with the IBM i system +is necessary. + +@param data The BLOB data. +**/ + AS400JDBCBlob(byte[] data, int maxLength) + { + data_ = data; + maxLength_ = maxLength; + } + + + +/** +Returns the entire BLOB as a stream of uninterpreted bytes. + +@return The stream. + +@exception SQLException If an error occurs. +**/ + public synchronized InputStream getBinaryStream() throws SQLException + { + //Following Native, throw HY010 after free() has been called + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + return new ByteArrayInputStream(data_); + } + + + +/** +Returns part of the contents of the BLOB. + +@param position The start position within the BLOB (1-based). +@param length The length to return. +@return The contents. + +@exception SQLException If the start position is not valid, + if the length is not valid, + or an error occurs. +**/ + public synchronized byte[] getBytes(long position, int length) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + if (offset < 0 || length < 0 || (offset + length) > data_.length) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int lengthToUse = data_.length - offset; + if (lengthToUse < 0) return new byte[0]; + if (lengthToUse > length) lengthToUse = length; + + byte[] result = new byte[lengthToUse]; + System.arraycopy(data_, offset, result, 0, lengthToUse); + return result; + } + + + +/** +Returns the length of the BLOB. + +@return The length of the BLOB, in bytes. + +@exception SQLException If an error occurs. +**/ + public synchronized long length() throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + return data_.length; + } + + +/** +Returns the position at which a pattern is found in the BLOB. + +@param pattern The pattern. +@param position The position within the BLOB to begin + searching (1-based). +@return The position at which the pattern + is found, or -1 if the pattern is not + found. + +@exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. +**/ + public synchronized long position(byte[] pattern, long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= data_.length) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } else { + + int end = data_.length - pattern.length; + + for (int i=offset; i<=end; ++i) + { + int j = 0; + while (j < pattern.length && data_[i+j] == pattern[j]) ++j; + if (j == pattern.length) return i+1; + } + } + return -1; + } + + +/** +Returns the position at which a pattern is found in the BLOB. + +@param pattern The pattern. +@param position The position within the BLOB to begin + searching (1-based). +@return The position at which the pattern + is found, or -1 if the pattern is not + found. + +@exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. +**/ + public synchronized long position(Blob pattern, long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= data_.length) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } else { + + int patternLength = (int)pattern.length(); + if (patternLength > data_.length || patternLength < 0) return -1; + + int end = data_.length - patternLength; + + byte[] bytePattern = pattern.getBytes(1L, patternLength); //@CRS - Get all bytes for now, improve this later. + + for (int i=offset; i<=end; ++i) + { + int j = 0; + while (j < patternLength && data_[i+j] == bytePattern[j]) ++j; + if (j == patternLength) return i+1; + } + } + return -1; + } + + + + /** + Returns a stream that an application can use to write to this BLOB. + The stream begins at position positionToStartWriting. + + @param position The position (1-based) in the BLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public synchronized OutputStream setBinaryStream(long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + return new AS400JDBCBlobOutputStream(this, position); + } + + /** + * This is not part of the JDBC interface. + **/ + synchronized int setByte(long position, byte data) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + + if (offset < 0 || offset >= maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int newSize = offset + 1; + if (newSize < 0) newSize = 0x7FFFFFFF; + if (newSize > data_.length) + { + byte[] temp = data_; + data_ = new byte[newSize]; + System.arraycopy(temp, 0, data_, 0, temp.length); + } + int numBytes = newSize - offset; + if (numBytes > 0) + { + data_[offset] = data; + return 1; + } + return 0; + } + + + + /** + Writes an array of bytes to this BLOB, starting at position positionToStartWriting + in the BLOB. + + @param position The position (1-based) in the BLOB where writes should start. + @param bytesToWrite The array of bytes to be written to this BLOB. + @return The number of bytes written to the BLOB. + + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public synchronized int setBytes(long position, byte[] bytesToWrite) throws SQLException + { + if(data_ == null) { //@free + throw JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + } + + + int offset = (int)position-1; + + if (offset < 0 || offset >= maxLength_ || bytesToWrite == null) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many bytes as we can. If our internal byte array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of bytes that were set. + int newSize = offset + bytesToWrite.length; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + if (newSize > data_.length) + { + byte[] temp = data_; + data_ = new byte[newSize]; + System.arraycopy(temp, 0, data_, 0, temp.length); + } + int numBytes = newSize - offset; + System.arraycopy(bytesToWrite, 0, data_, offset, numBytes); + + return numBytes; + } + + + + /** + Writes all or part of the byte array the application passes in to this BLOB, + starting at position position in the BLOB. + The BLOB will be truncated after the last byte written. The lengthOfWrite + bytes written will start from offset in the bytes that were provided by the + application. + + @param position The position (1-based) in the BLOB where writes should start. + @param bytesToWrite The array of bytes to be written to this BLOB. + @param offset The offset into the array at which to start reading bytes (0-based). + @param lengthOfWrite The number of bytes to be written to the BLOB from the array of bytes. + @return The number of bytes written. + + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public synchronized int setBytes(long position, byte[] bytesToWrite, int offset, int lengthOfWrite) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int blobOffset = (int)position-1; + if (blobOffset < 0 || blobOffset >= maxLength_ || + bytesToWrite == null || offset < 0 || lengthOfWrite < 0 || (offset+lengthOfWrite) > bytesToWrite.length || + (blobOffset+lengthOfWrite) > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many bytes as we can. If our internal byte array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of bytes that were set. + int newSize = blobOffset + lengthOfWrite; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + if (newSize > data_.length) + { + byte[] temp = data_; + data_ = new byte[newSize]; + System.arraycopy(temp, 0, data_, 0, temp.length); + } + int numBytes = newSize - blobOffset; + System.arraycopy(bytesToWrite, offset, data_, blobOffset, numBytes); + + return numBytes; + } + + + + /** + Truncates this BLOB to a length of lengthOfBLOB bytes. + + @param lengthOfBLOB The length, in bytes, that this BLOB should be after + truncation. + + @exception SQLException If there is an error accessing the BLOB. + **/ + public synchronized void truncate(long lengthOfBLOB) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int length = (int)lengthOfBLOB; + if (length < 0 || length > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + byte[] temp = data_; + data_ = new byte[length]; + int numToCopy = length < temp.length ? length : temp.length; + System.arraycopy(temp, 0, data_, 0, numToCopy); + } + + + // @PDA jdbc40 + /** + * This method frees the Blob object and releases the + * resources that it holds. The object is invalid once the free + * method is called. If free is called multiple times, the + * subsequent calls to free are treated as a no-op. + * + * @throws SQLException + * if an error occurs releasing the Blob's resources + */ + public synchronized void free() throws SQLException + { + data_ = null; //@pda make available for GC + } + + // @PDA jdbc40 + /** + * Returns an InputStream object that contains a partial + * Blob value, starting with the byte specified by pos, which + * is length bytes in length. + * + * @param pos + * the offset to the first byte of the partial value to be + * retrieved. The first byte in the Blob is at + * position 1 + * @param length + * the length in bytes of the partial value to be retrieved + * @return InputStream through which the partial + * Blob value can be read. + * @throws SQLException + * if pos is less than 1 or if pos is greater than the number of + * bytes in the Blob or if pos + length is + * greater than the number of bytes in the Blob + */ + public synchronized InputStream getBinaryStream(long pos, long length) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + return new ByteArrayInputStream(data_, (int)pos, (int)length); + } + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCBlobLocator.java b/jdbc40/com/ibm/as400/access/AS400JDBCBlobLocator.java new file mode 100644 index 000000000..ef53b87c8 --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCBlobLocator.java @@ -0,0 +1,508 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCBlobLocator.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; + +// Note: This code in this class requires understanding of bit manipulation +// and sign extension. Do not attempt to rework this code if you do not +// have a grasp of these concepts. + +// Currently, the database host server only supports 2 GB LOBs. Therefore, +// we validate any long parameters to make sure they are not greater than +// the maximum positive value for a 4-byte int (2 GB). This has the added +// bonus of being able to cast the long down to an int without worrying +// about sign extension. There are some cases where we could allow the +// user to pass in a long greater than 2 GB, but for consistency, we will +// throw an exception. + +// Offset refers to a 0-based index. Position refers to a 1-based index. + + +/** +The AS400JDBCBlobLocator class provides access to binary large +objects. The data is valid only within the current +transaction. +**/ +public class AS400JDBCBlobLocator implements Blob +{ + static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others."; + + + JDLobLocator locator_; + Object savedObject_; // This is our InputStream or byte[] or whatever that needs to be written if we are batching. + int savedScale_; // This is our length that goes with our savedObject_. + + private byte[] cache_; + private int cacheOffset_; + private static final byte[] INIT_CACHE = new byte[0]; + private int maxLength_; + +/** +Constructs an AS400JDBCBlobLocator object. The data for the +BLOB will be retrieved as requested, directly from the +IBM i system, using the locator handle. + +@param locator The locator. +**/ + AS400JDBCBlobLocator(JDLobLocator locator, Object savedObject, int savedScale) + { + locator_ = locator; + savedObject_ = savedObject; + savedScale_ = savedScale; + maxLength_ = locator_.getMaxLength(); + } + + + +/** +Returns the entire BLOB as a stream of uninterpreted bytes. + +@return The stream. + +@exception SQLException If an error occurs. +**/ + public InputStream getBinaryStream() throws SQLException + { + //Following Native, throw HY010 after free() has been called. Note: NullPointerException if synchronized(null-ref) + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + return new AS400JDBCInputStream(locator_); + } + } + + + +/** +Returns part of the contents of the BLOB. + +@param position The position within the BLOB (1-based). +@param length The length to return. +@return The contents. + +@exception SQLException If the position is not valid, + if the length is not valid, + or an error occurs. +**/ + public byte[] getBytes(long position, int length) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (offset < 0 || length < 0 || (offset + length) > locator_.getLength()) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + int lengthToUse = (int)locator_.getLength() - offset; + if (lengthToUse <= 0) return new byte[0]; + if (lengthToUse > length) lengthToUse = length; + + DBLobData data = locator_.retrieveData(offset, lengthToUse); + int actualLength = data.getLength(); + byte[] bytes = new byte[actualLength]; + System.arraycopy(data.getRawBytes(), data.getOffset(), bytes, 0, actualLength); + return bytes; + } + } + + + +/** +Returns the handle to this BLOB locator in the database. + +@return The handle to this locator in the database. +**/ + public int getHandle() throws SQLException //@free called from rs.updateValue(), which in turn will throw exc back to rs.updateX() caller + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + return locator_.getHandle(); + } + + + +/** +Returns the length of the BLOB. + +@return The length of the BLOB, in bytes. + +@exception SQLException If an error occurs. +**/ + public long length() throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + return locator_.getLength(); + } + } + + // Used for position(). + private void initCache() + { + cacheOffset_ = 0; + cache_ = INIT_CACHE; + } + + // Used for position(). + private int getCachedByte(int index) throws SQLException + { + int realIndex = index - cacheOffset_; + if (realIndex >= cache_.length) + { + int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; + int len = (int)locator_.getLength(); + if (len < 0) len = 0x7FFFFFFF; + if ((blockSize+index) > len) blockSize = len-index; + cache_ = getBytes(index+1, blockSize); + cacheOffset_ = index; + realIndex = 0; + } + if (cache_.length == 0) return -1; + return cache_[realIndex]; + } + + +/** +Returns the position at which a pattern is found in the BLOB. + +@param pattern The pattern. +@param position The position within the BLOB to begin + searching (1-based). +@return The offset into the BLOB at which the pattern was found, + or -1 if the pattern was not found or the pattern was a byte + array of length 0. + +@exception SQLException If the position is not valid or an error occurs. +**/ + public long position(byte[] pattern, long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= locator_.getLength()) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int end = (int)locator_.getLength() - pattern.length; + + // We use a cache of bytes so we don't have to read in the entire + // contents of the BLOB. + initCache(); + + for (int i=offset; i<=end; ++i) + { + int j = 0; + int cachedByte = getCachedByte(i+j); + while (j < pattern.length && cachedByte != -1 && pattern[j] == (byte)cachedByte) + { + ++j; + cachedByte = getCachedByte(i+j); + } + if (j == pattern.length) return i+1; + } + return -1; + } + } + + + +/** +Returns the position at which a pattern is found in the BLOB. + +@param pattern The pattern. +@param position The position within the BLOB to begin + searching (1-based). +@return The offset into the BLOB at which the pattern was found, + or -1 if the pattern was not found or the pattern was a byte + array of length 0. + +@exception SQLException If the position is not valid or an error occurs. +**/ + public long position(Blob pattern, long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= locator_.getLength()) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int patternLength = (int)pattern.length(); + int locatorLength = (int)locator_.getLength(); + if (patternLength > locatorLength || patternLength < 0) return -1; + + int end = locatorLength - patternLength; + + byte[] bytePattern = pattern.getBytes(1L, patternLength); //@CRS - Get all bytes for now, improve this later. + + // We use a cache of bytes so we don't have to read in the entire + // contents of the BLOB. + initCache(); + + for (int i=offset; i<=end; ++i) + { + int j = 0; + int cachedByte = getCachedByte(i+j); + while (j < patternLength && cachedByte != -1 && bytePattern[j] == (byte)cachedByte) + { + ++j; + cachedByte = getCachedByte(i+j); + } + if (j == patternLength) return i+1; + } + + return -1; + } + } + + + /** + Returns a stream that an application can use to write to this BLOB. + The stream begins at position position. + + @param position The position (1-based) in the BLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public OutputStream setBinaryStream(long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + return new AS400JDBCBlobLocatorOutputStream(this, position); + } + + + + /** + Writes an array of bytes to this BLOB, starting at position position + in the BLOB. + + @param position The position (1-based) in the BLOB where writes should start. + @param bytesToWrite The array of bytes to be written to this BLOB. + @return The number of bytes written to the BLOB. + + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public int setBytes(long position, byte[] bytesToWrite) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + + if (offset < 0 || offset >= maxLength_ || bytesToWrite == null) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many bytes as we can. If the byte array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of bytes that could be set. + int newSize = offset + bytesToWrite.length; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + int numBytes = newSize - offset; + if (numBytes != bytesToWrite.length) + { + byte[] temp = bytesToWrite; + bytesToWrite = new byte[numBytes]; + System.arraycopy(temp, 0, bytesToWrite, 0, numBytes); + } + + // We don't really know if all of these bytes can be written until we go to + // the system, so we just return the byte[] length as the number written. + locator_.writeData((long)offset, bytesToWrite, false); //@K1A + return bytesToWrite.length; + } + } + + + + /** + Writes all or part of the byte array the application passes in to this BLOB, + starting at position position in the BLOB. + The lengthOfWrite + bytes written will start from offset in the bytes that were provided by the + application. + + @param position The position (1-based) in the BLOB where writes should start. + @param bytesToWrite The array of bytes to be written to this BLOB. + @param offset The offset into the array at which to start reading bytes (0-based). + @param lengthOfWrite The number of bytes to be written to the BLOB from the array of bytes. + @return The number of bytes written. + + @exception SQLException If there is an error accessing the BLOB or if the position + specified is greater than the length of the BLOB. + **/ + public int setBytes(long position, byte[] bytesToWrite, int offset, int lengthOfWrite) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int blobOffset = (int)position-1; + if (blobOffset < 0 || blobOffset >= maxLength_ || + bytesToWrite == null || offset < 0 || lengthOfWrite < 0 || (offset+lengthOfWrite) > bytesToWrite.length || + (blobOffset+lengthOfWrite) > maxLength_) + { + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many bytes as we can. If the byte array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of bytes that could be set. + int newSize = blobOffset + lengthOfWrite; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + int numBytes = newSize - blobOffset; + int realLength = (numBytes < lengthOfWrite ? numBytes : lengthOfWrite); + byte[] newData = new byte[realLength]; + System.arraycopy(bytesToWrite, offset, newData, 0, lengthOfWrite); + + // We don't really know if all of these bytes can be written until we go to + // the system, so we just return the byte[] length as the number written. + locator_.writeData((long)blobOffset, newData, false); //@K1A + return newData.length; + } + } + + + + /** + Truncates this BLOB to a length of lengthOfBLOB bytes. + + @param lengthOfBLOB The length, in bytes, that this BLOB should be after + truncation. + + @exception SQLException If there is an error accessing the BLOB or if the length + specified is greater than the length of the BLOB. + **/ + public void truncate(long lengthOfBLOB) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int length = (int)lengthOfBLOB; + if (length < 0 || length > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + // The host server does not currently provide a way for us + // to truncate the temp space used to hold the locator data, + // so we just keep track of it ourselves. This should work, + // since the temp space on the system should only be valid + // within the scope of our transaction/connection. That means + // there's no reason to go to the system to update the data, + // since no other process can get at it. + locator_.writeData(length, new byte[0], 0, 0, true); //@K1A + } + } + + //@PDA 550 + /** + * This method frees the Blob object and releases the + * resources that it holds. The object is invalid once the free + * method is called. If free is called multiple times, the + * subsequent calls to free are treated as a no-op. + * + * @throws SQLException + * if an error occurs releasing the Blob's resources + */ + public void free() throws SQLException //@sync + { + if(locator_ == null) + return; //no-op + + synchronized(locator_) //@sync + { + locator_.free(); + + locator_ = null; //@pda make objects available for GC + savedObject_ = null; + cache_ = null; + } + } + + + // @PDA jdbc40 + /** + * Returns an InputStream object that contains a partial + * Blob value, starting with the byte specified by pos, which + * is length bytes in length. + * + * @param pos + * the offset to the first byte of the partial value to be + * retrieved. The first byte in the Blob is at + * position 1 + * @param length + * the length in bytes of the partial value to be retrieved + * @return InputStream through which the partial + * Blob value can be read. + * @throws SQLException + * if pos is less than 1 or if pos is greater than the number of + * bytes in the Blob or if pos + length is + * greater than the number of bytes in the Blob + */ + public InputStream getBinaryStream(long pos, long length) throws SQLException //@sync + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + return new AS400JDBCInputStream(locator_, pos, length); + } + } + + /** Get the locator handle corresponding to this ClobLocator + * + */ + public int getLocator() { + return locator_.getHandle(); + } + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCCallableStatement.java b/jdbc40/com/ibm/as400/access/AS400JDBCCallableStatement.java new file mode 100644 index 000000000..0f3d1f25f --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCCallableStatement.java @@ -0,0 +1,4630 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCCallableStatement.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.InputStream; //@G4A +import java.io.Reader; //@G4A +import java.math.BigDecimal; +import java.net.MalformedURLException; //@G4A +import java.net.URL; //@G4A +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.DataTruncation; +import java.sql.Date; +/* ifdef JDBC40 */ +import java.sql.NClob; +/* endif */ +import java.sql.Ref; +/* ifdef JDBC40 */ +import java.sql.ResultSet; //@G4A +import java.sql.RowId; +/* endif */ +import java.sql.SQLException; +/* ifdef JDBC40 */ +import java.sql.SQLXML; +import java.sql.Statement; //@G4A +/* endif */ +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; +import java.util.Map; +/* ifdef JDBC40 */ +import java.util.Hashtable; //@G4A +import java.util.Vector; +/* endif */ + + +/** +

The AS400JDBCCallableStatement class runs a stored procedure. +Use Connection.prepareCall() to create new CallableStatement +objects. + +

Parameters are indexed sequentially, by number, starting +at 1. The caller must register output parameters before executing +the stored procedure. + +

The new JDK 1.4 methods add the ability to +retrieve information by column name in addition to column index. +Be aware you will see better performance accessing columns by their +index rather than accessing them by their name. +**/ +public class AS400JDBCCallableStatement +extends AS400JDBCPreparedStatement +implements CallableStatement +{ + static final String copyright2 = "Copyright (C) 1997-2006 International Business Machines Corporation and others."; + + static final int NO_VALIDATION_ = -9999; + + private int[] registeredTypes_; // array of types to track what the user registers the output parm as + private boolean[] registered_; // array of booleans to keep track of which parameters were registered + + private boolean returnValueParameterRegistered_; // @E2A + private boolean wasNull_; + private boolean wasDataMappingError_; + + //private String[] parameterNames_; //@PDD jdbc40 move to preparedStatement + private int maxToLog_ = 10000; // Log value of parameter markers up to this length // @G7A + + private Object byteArrayClass_; + + /** + Constructs an AS400JDBCCallableStatement object. + + @param connection The connection to the system. + @param id The id. + @param transactionManager The transaction manager for the connection. + @param packageManager The package manager for the connection. + @param blockCriteria The block criteria. + @param blockSize The block size (in KB). + @param sqlStatement The SQL statement. + @parma packageCriteria The package criteria. + @param resultSetType The result set type. + @param resultSetConcurrency The result set concurrency. + @param resultSetHoldability The result set holdability. + @param generatedKeysRequested The generated keys requested. + + @exception SQLException If the SQL statement contains a syntax + error or an error occurs. + **/ + AS400JDBCCallableStatement(AS400JDBCConnection connection, + int id, + JDTransactionManager transactionManager, + JDPackageManager packageManager, + String blockCriteria, + int blockSize, + JDSQLStatement sqlStatement, + String packageCriteria, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability, //@G4A + int generatedKeysRequested) //@G4A + throws SQLException + { + // Turn off pre-fetch, since the output parameter values + // come back as result data. If we prefetched data, + // we would not be able to differentiate between + // pre-fetched data from the output parameter values. + super(connection, id, transactionManager, + packageManager, blockCriteria, blockSize, + false, sqlStatement, true, packageCriteria, + resultSetType, resultSetConcurrency, resultSetHoldability, + generatedKeysRequested); + + registeredTypes_ = new int[parameterCount_]; + registered_ = new boolean[parameterCount_]; + for(int i = 0; i < parameterCount_; ++i) + { + registered_[i] = false; + } + + returnValueParameterRegistered_ = false; // @E2A + + wasNull_ = false; + wasDataMappingError_ = false; + } + + // @C1A + /** + Performs common operations needed before an execute. + + @param sqlStatement The SQL statement. + @param request The execute request. + + @exception SQLException If an error occurs. + **/ + void commonExecuteBefore(JDSQLStatement sqlStatement, DBSQLRequestDS request) + throws SQLException + { + // Validate each parameters. If a parameter is not an + // output parameter, then it is okay for it not to have been + // registered. However, if an output parameter was not + // registered, we throw an exception. + for(int i = 0; i < parameterCount_; ++i) + if((registered_[i] == false) && (parameterRow_.isOutput(i+1))) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_COUNT_MISMATCH); + + super.commonExecuteBefore(sqlStatement, request); + } + + //@G4A + /* + Find the column index that matches this parameter name. + @param parameterName The parameter name to change into a column index (1-based). + */ + //@PDD jdbc40 move method to preparedStatement + /*int findParameterIndex(String parameterName) + throws SQLException + { + // Throw an exception if null was passed in + if(parameterName == null) + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + // Throw an exception if the Statement is closed (FUNCTION SEQUENCE) + if(isClosed()) + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); + + boolean caseSensitive = false; + int count = 0; + int returnParm = 0; + + // determine if our search should be case insensitive or not + if(parameterName.startsWith("\"") && parameterName.endsWith("\"")) // assume no leading or trailing blanks + + { + parameterName = JDUtilities.stripOuterDoubleQuotes(parameterName); + + caseSensitive = true; + } + + // If we have a cache created, try to find the column name in it. + if(parameterNames_ != null) + { + // Look up the mapping in our cache. + while(count < parameterNames_.length) + { + if (parameterNames_[count] != null) + { + if((caseSensitive && parameterNames_[count].equals(parameterName)) + || (!caseSensitive && parameterNames_[count].equalsIgnoreCase(parameterName))) + { + returnParm = count+1; + break; + } + } + + ++count; + } + } + else + { + // Else, create a new hash table to hold all the column name/number mappings. + parameterNames_ = new String[parameterCount_]; + + // Cache all the parm names and numbers. + Statement s = null; //@scan1 + ResultSet rs = null; //@scan1 + try{ + s = connection_.createStatement(); + String catalogSeparator = ""; //@74A Added a check for the naming used. Need to use separator appropriate to naming. + if (connection_.getProperties().equals (JDProperties.NAMING, JDProperties.NAMING_SQL)) //@74A + catalogSeparator = "."; //@74A + else //@74A + catalogSeparator = "/"; //@74A + + String schema = sqlStatement_.getSchema(); + if(schema == null || schema.equals("")) // no schema in statement + { // Derive the schema. + schema = connection_.getDefaultSchema(true); // get raw value + + if(schema == null) // No default SQL schema was set on the connection url, or by the libraries connection property. + { + if(catalogSeparator.equals(".")) // using sql naming + { + schema = connection_.getUserName(); // set to user profile + } + else // using system naming + { + // Retrieve the library list from the IBM i - Use ROI Retrieve Library List. + ResultSet rs1 = JDUtilities.getLibraries(this, connection_, null, true); + Vector libListV = new Vector(); + while(rs1.next()) { + libListV.addElement(rs1.getString(1)); + } + rs1.close(); //@SS + String[] libList = new String[libListV.size()]; + libListV.toArray(libList); + + // Get a result set that we can scroll forward/backward through. + Statement s1 = connection_.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + rs = s1.executeQuery("SELECT ROUTINE_SCHEMA FROM QSYS2" + + catalogSeparator + + "SYSPROCS WHERE ROUTINE_NAME='" + + unquote(sqlStatement_.getProcedure()) + + "' AND IN_PARMS + OUT_PARMS + INOUT_PARMS = " + + parameterCount_);//@scan1 + if(!rs.next()) + JDError.throwSQLException(this, JDError.EXC_INTERNAL); // didn't find the procedure in any schema + + // If we get this far, at least one schema contains a procedure similar to ours. + boolean found = false; + for(int i=0; i parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + switch(registeredTypes_[parameterIndex-1]) { + case Types.ARRAY: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Array value = (data == null) ? null : data.getArray(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL ARRAY output parameter as an Array value. + DB2 for IBM i does not support arrays. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + + **/ + public Array getArray(String parameterName) + throws SQLException + { + return getArray(findParameterIndex(parameterName)); //@array3 + } + + // JDBC 2.0 + /** + Returns the value of an SQL NUMERIC or DECIMAL output parameter as a + BigDecimal object. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public BigDecimal getBigDecimal(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registeredTypes_[parameterIndex-1] == -1) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + BigDecimal value = (data == null) ? null : data.getBigDecimal(-1); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + /** + Returns the value of an SQL NUMERIC or DECIMAL output parameter as a + BigDecimal object. + + @param parameterIndex The parameter index (1-based). + @param scale The number of digits after the decimal. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the scale is not valid, + the statement was not executed, or + the requested conversion is not valid. + + @deprecated Use getBigDecimal(int) or getBigDecimal(String) instead. + @see #getBigDecimal(int) + **/ + public BigDecimal getBigDecimal(int parameterIndex, int scale) + throws SQLException + { + // Check for negative scale. + if(scale < 0) + JDError.throwSQLException(this, JDError.EXC_SCALE_INVALID,""+scale); + + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1] ); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + BigDecimal value = (data == null) ? null : data.getBigDecimal(scale); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL NUMERIC or DECIMAL output parameter as a + BigDecimal object. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public BigDecimal getBigDecimal(String parameterName) + throws SQLException + { + return getBigDecimal(findParameterIndex(parameterName)); + } + + // JDBC 2.0 + /** + Returns the value of an SQL BLOB output parameter as a Blob value. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Blob getBlob(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID,""+parameterIndex); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + switch (registeredTypes_[parameterIndex - 1]) { + case Types.BLOB: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Blob value = (data == null) ? null : data.getBlob(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL BLOB output parameter as a Blob value. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Blob getBlob(String parameterName) + throws SQLException + { + return getBlob(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL SMALLINT output parameter as a + Java boolean. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or false if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIT, but DB2 for IBM i + // does not support that. + // + public boolean getBoolean(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + // 16 is the value of Types.BOOLEAN added for JDK 1.4 + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + boolean value = (data == null) ? false : data.getBoolean(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL SMALLINT output parameter as a + Java boolean. + + @param parameterName The parameter name. + @return The parameter value or false if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIT, but DB2 for IBM i + // does not support that. + // + public boolean getBoolean(String parameterName) + throws SQLException + { + return getBoolean(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL SMALLINT output parameter as a + Java byte. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid, + or an error occurs. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL TINYINT, but DB2 for IBM i + // does not support that. + // + public byte getByte(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + byte value = (data == null) ? 0 : data.getByte(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL SMALLINT output parameter as a + Java byte. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid, + or an error occurs. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL TINYINT, but DB2 for IBM i + // does not support that. + // + public byte getByte(String parameterName) + throws SQLException + { + return getByte(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL BINARY or VARBINARY output parameter as a + Java byte array. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public byte[] getBytes(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + //if(registeredTypes_[parameterIndex-1] != Types.BINARY && registeredTypes_[parameterIndex-1] != Types.VARBINARY) + // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + byte[] value = (data == null) ? null : data.getBytes(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL BINARY or VARBINARY output parameter as a + Java byte array. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public byte[] getBytes(String parameterName) + throws SQLException + { + return getBytes(findParameterIndex(parameterName)); + } + + // JDBC 2.0 + /** + Returns the value of an SQL CLOB output parameter as a Clob value. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Clob getClob(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + switch (registeredTypes_[parameterIndex - 1]) { + case Types.CLOB: + case 2011: /* nclob */ + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Clob value = (data == null) ? null : data.getClob(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL CLOB output parameter as a Clob value. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Clob getClob(String parameterName) + throws SQLException + { + return getClob(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL DATE output parameter as a + java.sql.Date object using the default calendar. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Date getDate(int parameterIndex) + throws SQLException + { + return getDate(parameterIndex, AS400Calendar.getGregorianInstance()); + } + + // JDBC 2.0 + /** + Returns the value of an SQL DATE output parameter as a + java.sql.Date object using a calendar other than the default. + + @param parameterIndex The parameter index (1-based). + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Date getDate(int parameterIndex, Calendar calendar) + throws SQLException + { + // Check for null calendar. + if(calendar == null) + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + // Changed 9/29/2011 for JDBC 4.1 + // The getter method says this can be used again several type other than Types.DATE + switch(registeredTypes_[parameterIndex-1]) { + case Types.DATE: + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.TIMESTAMP: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Date value = (data == null) ? null : data.getDate(calendar); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL DATE output parameter as a + java.sql.Date object using the default calendar. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + + public Date getDate(String parameterName) + throws SQLException + { + return getDate(findParameterIndex(parameterName)); + } + + // JDBC 2.0 + /** + Returns the value of an SQL DATE output parameter as a + java.sql.Date object using a calendar other than the default. + + @param parameterName The parameter name. + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Date getDate(String parameterName, Calendar calendar) + throws SQLException + { + return getDate(findParameterIndex(parameterName), calendar); + } + + /** + Returns the value of an SQL DOUBLE or FLOAT output parameter as a + Java double. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public double getDouble(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + double value = (data == null) ? 0 : data.getDouble(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL DOUBLE or FLOAT output parameter as a + Java double. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public double getDouble(String parameterName) + throws SQLException + { + return getDouble(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL REAL or FLOAT output parameter as a + Java float. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public float getFloat(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + float value = (data == null) ? 0 : data.getFloat(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL REAL or FLOAT output parameter as a + Java float. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public float getFloat(String parameterName) + throws SQLException + { + return getFloat(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL INTEGER output parameter as a + Java int. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public int getInt(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + int value = (data == null) ? 0 : data.getInt(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL INTEGER output parameter as a + Java int. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public int getInt(String parameterName) + throws SQLException + { + return getInt(findParameterIndex(parameterName)); + } + + // @D0C + /** + If the connected system supports SQL BIGINT data, this returns + the value of an SQL BIGINT output parameter as a Java long. + Otherwise, this returns the value of an SQL INTEGER output + parameter as a Java long. SQL BIGINT data is supported on V4R5 + and later. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIGINT, but DB2 for IBM i + // does not support that until V4R5. + // + public long getLong(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + long value = (data == null) ? 0 : data.getLong(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + If the connected system supports SQL BIGINT data, this returns + the value of an SQL BIGINT output parameter as a Java long. + Otherwise, this returns the value of an SQL INTEGER output + parameter as a Java long. SQL BIGINT data is supported on V4R5 + and later. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIGINT, but DB2 for IBM i + // does not support that until V4R5. + // + public long getLong(String parameterName) + throws SQLException + { + return getLong(findParameterIndex(parameterName)); + } + + /** + Returns the value of an output parameter as a Java Object. + The type of the object corresponds to the SQL type that was + registered for this parameter using registerOutParameter(). + When the parameter is a user-defined type, then the + connection's type map is used to create the object. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Object getObject(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + if(data == null) + return null; + Object value = (data == null) ? null : data.getObject(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + // JDBC 2.0 + /** + Returns the value of an output parameter as a Java Object. + This driver does not support the type map. + + @param parameterIndex The parameter index (1-based). + @param typeMap The type map. This is not used. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Object getObject(int parameterIndex, Map typeMap) + throws SQLException + { + // Check for null type map, even though we don't use it. + if(typeMap == null) + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + return getObject(parameterIndex); + } + + //@G4A JDBC 3.0 + /** + Returns the value of an output parameter as a Java Object. + The type of the object corresponds to the SQL type that was + registered for this parameter using registerOutParameter(). + When the parameter is a user-defined type, then the + connection's type map is used to create the object. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Object getObject(String parameterName) + throws SQLException + { + return getObject(findParameterIndex(parameterName)); + } + + //@G4A JDBC 3.0 + /** + Returns the value of an output parameter as a Java Object. + This driver does not support the type map. + + @param parameterName The parameter name. + @param typeMap The type map. This is not used. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Object getObject(String parameterName, Map typeMap) + throws SQLException + { + return getObject(findParameterIndex(parameterName)); + } + + // JDBC 2.0 + /** + Returns the value of an SQL REF output parameter as a Ref value. + DB2 for IBM i does not support structured types. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException Always thrown because DB2 for IBM i does not support REFs. + **/ + public Ref getRef(int parameterIndex) + throws SQLException + { + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + return null; + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL REF output parameter as a Ref value. + DB2 for IBM i does not support structured types. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException Always thrown because DB2 for IBM i does not support REFs. + **/ + public Ref getRef(String parameterName) + throws SQLException + { + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + return null; + } + + /** + Returns the value of an SQL SMALLINT output parameter as a + Java short value. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public short getShort(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + validateNumericRegisteredType(registeredTypes_[parameterIndex-1]); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + short value = (data == null) ? 0 : data.getShort(); + testDataTruncation(parameterIndex, data, true); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL SMALLINT output parameter as a + Java short value. + + @param parameterName The parameter name. + @return The parameter value or 0 if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public short getShort(String parameterName) + throws SQLException + { + return getShort(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL CHAR or VARCHAR output + parameter as a Java String object. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public String getString(int parameterIndex) + throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + //if(registeredTypes_[parameterIndex-1] != Types.CHAR && registeredTypes_[parameterIndex-1] != Types.VARCHAR) + // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + String value = (data == null) ? null : data.getString(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL CHAR or VARCHAR output + parameter as a Java String object. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public String getString(String parameterName) + throws SQLException + { + return getString(findParameterIndex(parameterName)); + } + + /** + Returns the value of an SQL TIME output parameter as a + java.sql.Time object using the default calendar. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Time getTime(int parameterIndex) + throws SQLException + { + return getTime(parameterIndex, AS400Calendar.getGregorianInstance()); + } + + // JDBC 2.0 + /** + Returns the value of an SQL TIME output parameter as a + java.sql.Time object using a calendar other than the + default. + + @param parameterIndex The parameter index (1-based). + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Time getTime(int parameterIndex, Calendar calendar) + throws SQLException + { + // Check for null calendar. + if(calendar == null) + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + // Changed 9/29/2011 for JDBC 4.1 + // The getter method says this can be used again several type other than Types.Time + + switch(registeredTypes_[parameterIndex-1]) { + case Types.TIME: + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.TIMESTAMP: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Time value = (data == null) ? null : data.getTime(calendar); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL TIME output parameter as a + java.sql.Time object using the default calendar. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Time getTime(String parameterName) + throws SQLException + { + return getTime(findParameterIndex(parameterName)); + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL TIME output parameter as a + java.sql.Time object using a calendar other than the + default. + + @param parameterName The parameter name. + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Time getTime(String parameterName, Calendar calendar) + throws SQLException + { + return getTime(findParameterIndex(parameterName), calendar); + } + + /** + Returns the value of an SQL TIMESTAMP output parameter as a + java.sql.Timestamp object using the default calendar. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Timestamp getTimestamp(int parameterIndex) + throws SQLException + { + return getTimestamp(parameterIndex, AS400Calendar.getGregorianInstance()); + } + + // JDBC 2.0 + /** + Returns the value of an SQL TIMESTAMP output parameter as a + java.sql.Timestamp object using a calendar other than the + default. + + @param parameterIndex The parameter index (1-based). + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Timestamp getTimestamp(int parameterIndex, Calendar calendar) + throws SQLException + { + // Check for null calendar. + if(calendar == null) + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + // Changed 9/29/2011 for JDBC 4.1 + // The getter method says this can be used again several type other than Types.TIMESTAMP + switch(registeredTypes_[parameterIndex-1]){ + + case Types.TIMESTAMP: + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.TIME: + case Types.DATE: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Timestamp value = (data == null) ? null : data.getTimestamp(calendar); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL TIMESTAMP output parameter as a + java.sql.Timestamp object using the default calendar. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + public Timestamp getTimestamp(String parameterName) + throws SQLException + { + return getTimestamp(findParameterIndex(parameterName)); + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL TIMESTAMP output parameter as a + java.sql.Timestamp object using a calendar other than the + default. + + @param parameterName The parameter name. + @param calendar The calendar. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed, + the calendar is null, or + the requested conversion is not valid. + **/ + public Timestamp getTimestamp(String parameterName, Calendar calendar) + throws SQLException + { + return getTimestamp(findParameterIndex(parameterName), calendar); + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL DATALINK output parameter as a + java.net.URL object. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed or + the requested conversion is not valid. + **/ + public URL getURL(int parameterIndex) throws SQLException { + synchronized (internalLock_) { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if (useReturnValueParameter_ && parameterIndex == 1) { + if (!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } else { + if (useReturnValueParameter_) { + --parameterIndex; + } + + // Validate the parameter index. + if ((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if (!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if (registered_[parameterIndex - 1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + switch (registeredTypes_[parameterIndex - 1]) { + case Types.CHAR: + case Types.VARCHAR: + case Types.DATALINK: + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + String value = (data == null) ? null : data.getString(); + testDataTruncation(parameterIndex, data, false); + if (value != null) { + try { + return new java.net.URL(value); + } catch (MalformedURLException e) { + JDError + .throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e); + return null; + } + } else { + return null; + } + } + } + + //@G4A JDBC 3.0 + /** + Returns the value of an SQL DATALINK output parameter as a + java.net.URL object. + + @param parameterName The parameter name. + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the name is not valid, the parameter name is + not registered as an output parameter, + the statement was not executed or + the requested conversion is not valid. + **/ + public URL getURL(String parameterName) + throws SQLException + { + return getURL(findParameterIndex(parameterName)); + } + + /** + Returns the value for an output parameter for the specified + index, and performs all appropriate validation. Also checks + for SQL NULL. + + @param parameterIndex The parameter index (1-based). + @return The parameter value or null if the value is SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, the index is + not registered as an output parameter, + the statement was not executed, or + the requested conversion is not valid. + **/ + private SQLData getValue(int parameterIndex) + throws SQLException + { + // Verify that the statement has been executed. + if(! executed_) + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); + + // Get the data and check for SQL NULL. + SQLData data = parameterRow_.getSQLData(parameterIndex); + wasNull_ = parameterRow_.isNull(parameterIndex); + wasDataMappingError_ = parameterRow_.isDataMappingError(parameterIndex); + + return wasNull_ ? null : data; + } + + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterIndex The parameter index (1-based). + @param sqlType The SQL type code defined in java.sql.Types. + @param scale The number of digits after the decimal + if sqlType is DECIMAL or NUMERIC. + + @exception SQLException If the index is not valid, + the scale is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(int parameterIndex, + int sqlType, + int scale) + throws SQLException + { + synchronized(internalLock_) + { // @E1A + checkOpen(); + + // Check if the parameter index refers to the return value parameter. @E2A + // If so, it must be registed as an INTEGER. @E2A + // If it is not parameter index 1, then decrement the parameter index, @E2A + // since we are "faking" the return value parameter. @E2A + if(useReturnValueParameter_) + { // @E2A + if(parameterIndex == 1) + { // @E2A + if(sqlType != Types.INTEGER) // @E2A + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); // @E2A + returnValueParameterRegistered_ = true; // @E2A + return; // @E2A + } // @E2A + else // @E2A + --parameterIndex; // @E2A + } // @E2A + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Validate the scale. + if(scale < 0) + JDError.throwSQLException(this, JDError.EXC_SCALE_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + registeredTypes_[parameterIndex-1] = sqlType; + registered_[parameterIndex-1] = true; + } + } + + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterIndex The parameter index (1-based). + @param sqlType The SQL type code defined in java.sql.Types. + + @exception SQLException If the index is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(int parameterIndex, int sqlType) + throws SQLException + { + registerOutParameter(parameterIndex, sqlType, 0); + } + + // @A1 - Added for JDK 2.0RC1 - typeName can be ignored, since it is not relevant to the AS/400. + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterIndex The parameter index (1-based). + @param sqlType The SQL type code defined in java.sql.Types. + @param typeName The fully-qualified name of an SQL structured type. This value will be ignored. + + @exception SQLException If the index is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(int parameterIndex, int sqlType, String typeName) + throws SQLException + { + registerOutParameter(parameterIndex, sqlType, 0); + } + + //@G4A JDBC 3.0 + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterName The parameter name. + @param sqlType The SQL type code defined in java.sql.Types. + + @exception SQLException If the index is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(String parameterName, int sqlType) + throws SQLException + { + registerOutParameter(findParameterIndex(parameterName), sqlType, 0); + } + + //@G4A JDBC 3.0 + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterName The parameter name. + @param sqlType The SQL type code defined in java.sql.Types. + @param scale The number of digits after the decimal + if sqlType is DECIMAL or NUMERIC. + + @exception SQLException If the index is not valid, + the scale is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(String parameterName, int sqlType, int scale) + throws SQLException + { + registerOutParameter(findParameterIndex(parameterName), sqlType, scale); + } + + //@G4A JDBC 3.0 + /** + Registers the type for an output parameter. Before + executing the stored procedure call, explicitly + register the type of each output parameter. When + reading the value of an output parameter, use a + get method that corresponds to the registered type. A + parameter that is used for both input and output can not + be registered with a different type than was used when + it was set. + + @param parameterName The parameter name. + @param sqlType The SQL type code defined in java.sql.Types. + @param typeName The fully-qualified name of an SQL structured type. This value will be ignored. + + @exception SQLException If the index is not valid, + the parameter is not an output parameter, + or the requested conversion is not valid. + **/ + public void registerOutParameter(String parameterName, int sqlType, String typeName) + throws SQLException + { + registerOutParameter(findParameterIndex(parameterName), sqlType, 0); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to an ASCII stream value. The driver + reads the data from the stream as needed until no more bytes + are available. The driver converts this to an SQL VARCHAR + value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param length The number of bytes in the stream. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + the length is not valid, + the input stream does not contain all + ASCII characters, or an error occurs + while reading the input stream. + **/ + public void setAsciiStream(String parameterName, InputStream parameterValue, int length) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setAsciiStream()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); // @G7A + } // @G7A + + setAsciiStream(findParameterIndex(parameterName), parameterValue, length); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a BigDecimal value. The driver converts + this to an SQL NUMERIC value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, or the parameter + is not an input parameter. + **/ + public void setBigDecimal(String parameterName, BigDecimal parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setBigDecimal()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setBigDecimal(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a binary stream value. The driver + reads the data from the stream as needed until no more bytes + are available. The driver converts this to an SQL VARBINARY + value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param length The number of bytes in the stream. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + the length is not valid, or + an error occurs while reading the + input stream. + **/ + public void setBinaryStream(String parameterName, InputStream parameterValue, int length) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setBinaryStream()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); // @G7A + } // @G7A + + setBinaryStream(findParameterIndex(parameterName), parameterValue, length); + } + + /** + Sets an input parameter to a Java boolean value. The driver + converts this to an SQL SMALLINT value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameterName is not valid, or + the parameter is not an input parameter. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIT, but DB2 for IBM i + // does not support that. + // + public void setBoolean(String parameterName, boolean parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setBoolean()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setBoolean(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java byte value. The driver + converts this to an SQL SMALLINT value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or + the parameter is not an input parameter. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL TINYINT, but DB2 for IBM i + // does not support that. + // + public void setByte(String parameterName, byte parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setByte()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setByte(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java byte array value. The driver + converts this to an SQL VARBINARY value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + **/ + public void setBytes(String parameterName, byte[] parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setBytes()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else { + StringBuffer parameterStringBuffer = new StringBuffer(); + Trace.printByteArray(parameterStringBuffer, parameterValue); + JDTrace.logInformation(this, "parameter index: " + + findParameterIndex(parameterName) + " value: " + + parameterStringBuffer.toString()); // @G7A + } + } // @G7A + + setBytes(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a character stream value. The driver + reads the data from the character stream as needed until no more + characters are available. The driver converts this to an SQL + VARCHAR value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param length The number of bytes in the reader. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + the length is not valid, + or an error occurs while reading the + character stream + **/ + public void setCharacterStream(String parameterName, Reader parameterValue, int length) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setCharacterStream()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); // @G7A + } // @G7A + + setCharacterStream(findParameterIndex(parameterName), parameterValue, length); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Date value using the + default calendar. The driver converts this to an SQL DATE + value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + + **/ + public void setDate(String parameterName, Date parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setDate()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setDate(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Date value using a + calendar other than the default. The driver converts this + to an SQL DATE value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param cal The calendar. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + or the calendar is null. + + **/ + public void setDate(String parameterName, Date parameterValue, Calendar cal) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setDate()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setDate(findParameterIndex(parameterName), parameterValue, cal); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java double value. The driver + converts this to an SQL DOUBLE value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid or + the parameter is not an input parameter. + **/ + public void setDouble(String parameterName, double parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setDouble()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setDouble(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java float value. The driver + converts this to an SQL REAL value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or + the parameter is not an input parameter. + **/ + // + // Note: The JDBC 1.22 specification states that this + // method should set an SQL FLOAT value. However, + // all tables map float to REAL. Otherwise, + // nothing is symetrical and certain INOUT + // parameters do not work. + // + public void setFloat(String parameterName, float parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setFloat()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setFloat(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java int value. The driver + converts this to an SQL INTEGER value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid or + the parameter is not an input parameter. + **/ + public void setInt(String parameterName, int parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setInt()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setInt(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java long value. + If the connected system supports SQL BIGINT data, the driver + converts this to an SQL BIGINT value. Otherwise, the driver + converts this to an SQL INTEGER value. SQL BIGINT data is + supported on V4R5 and later. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or + the parameter is not an input parameter. + **/ + // + // Implementation note: + // + // The spec defines this in terms of SQL BIGINT, but DB2 for IBM i + // does not support that until V4R5. + // + public void setLong(String parameterName, long parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setLong()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setLong(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to SQL NULL. + + @param parameterName The parameter name. + @param sqlType The SQL type code defined in java.sql.Types. + + @exception SQLException If the statement is not open, + the parameterName is not valid, + the parameter is not an input parameter, + or the SQL type is not valid. + **/ + public void setNull(String parameterName, int sqlType) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setNull()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + } // @G7A + + setNull(findParameterIndex(parameterName), sqlType); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to SQL NULL. + + @param parameterName The parameter name. + @param sqlType The SQL type code defined in java.sql.Types. + @param typeName The fully-qualified name of an SQL structured type. This value will be ignored. + + @exception SQLException If the statement is not open, + the index is not valid, + the parameter is not an input parameter, + or the SQL type is not valid. + **/ + public void setNull(String parameterName, int sqlType, String typeName) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setNull()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + } // @G7A + + setNull(findParameterIndex(parameterName), sqlType, typeName); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to an Object value. The driver converts + this to a value of an SQL type, depending on the type of the + specified value. The JDBC specification defines a standard + mapping from Java types to SQL types. In the cases where a + SQL type is not supported by DB2 for IBM i, the + next closest matching type + is used. +
If proxy support is in use, the Object must be serializable. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the index is not valid, + the parameter is not an input parameter, + the type of value is not supported, + or the parameter is not serializable + (when proxy support is in use). + **/ + public void setObject(String parameterName, Object parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setObject()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " type: " + parameterValue.getClass().getName()); // @G7A + } // @G7A + + setObject(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to an Object value. The driver converts + this to a value with the specified SQL type. +
If proxy support is in use, the Object must be serializable. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param targetSqlType The SQL type code defined in java.sql.Types. + + @exception SQLException If the statement is not open, + the index is not valid, + the parameter is not an input parameter, + the SQL type is not valid, + the scale is not valid, + or the parameter is not serializable + (when proxy support is in use). + **/ + public void setObject(String parameterName, Object parameterValue, int targetSqlType) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setObject()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " type: " + parameterValue.getClass().getName()); // @G7A + } // @G7A + + setObject(findParameterIndex(parameterName), parameterValue, targetSqlType); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to an Object value. The driver converts + this to a value with the specified SQL type. +
If proxy support is in use, the Object must be serializable. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param targetSqlType The SQL type code defined in java.sql.Types. + @param scale The number of digits after the decimal + if sqlType is DECIMAL or NUMERIC. + + @exception SQLException If the statement is not open, + the index is not valid, + the parameter is not an input parameter, + the SQL type is not valid, + the scale is not valid, + or the parameter is not serializable + (when proxy support is in use). + **/ + public void setObject(String parameterName, Object parameterValue, int targetSqlType, int scale) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setObject()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " type: " + parameterValue.getClass().getName()); // @G7A + } // @G7A + + setObject(findParameterIndex(parameterName), parameterValue, targetSqlType, scale); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a Java short value. The driver + converts this to an SQL SMALLINT value. + + @param parameterName The parameter name. + @param parameterValue The parameter value. + + @exception SQLException If the statement is not open, + the parameter name is not valid or + the parameter is not an input parameter. + **/ + public void setShort(String parameterName, short parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setShort()"); // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setShort(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a String value. The driver + converts this to an SQL VARCHAR value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + **/ + public void setString(String parameterName, String parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setString()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else if(parameterValue.length() > maxToLog_) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + parameterValue.length()); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue); // @G7A + } // @G7A + + setString(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Time value using the + default calendar. The driver converts this to an SQL TIME value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + **/ + public void setTime(String parameterName, Time parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setTime()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setTime(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Time value using a calendar + other than the default. The driver converts this to an SQL TIME + value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param cal The calendar. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + or the calendar is null. + **/ + public void setTime(String parameterName, Time parameterValue, Calendar cal) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setTime()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setTime(findParameterIndex(parameterName), parameterValue, cal); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Timestamp value using the + default calendar. The driver converts this to an SQL TIMESTAMP + value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + **/ + public void setTimestamp(String parameterName, Timestamp parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setTimeStamp()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setTimestamp(findParameterIndex(parameterName), parameterValue); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a java.sql.Timestamp value using a + calendar other than the default. The driver converts this to + an SQL TIMESTAMP value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + @param cal The calendar. + + @exception SQLException If the statement is not open, + the index is not valid, the parameter + is not an input parameter, + or the calendar is null. + **/ + public void setTimestamp(String parameterName, Timestamp parameterValue, Calendar cal) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setTimeStamp()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setTimestamp(findParameterIndex(parameterName), parameterValue, cal); + } + + //@G4A JDBC 3.0 + /** + Sets an input parameter to a URL value. The driver converts this to an + SQL DATALINK value. + + @param parameterName The parameter name. + @param parameterValue The parameter value or null to set + the value to SQL NULL. + + @exception SQLException If the statement is not open, + the parameter name is not valid, or the parameter + is not an input parameter. + **/ + public void setURL(String parameterName, URL parameterValue) + throws SQLException + { + if(JDTrace.isTraceOn()) + { // @G7A + JDTrace.logInformation(this, "setURL()"); // @G7A + if(parameterValue == null) // @G7A + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); // @G7A + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + parameterValue.toString()); // @G7A + } // @G7A + + setURL(findParameterIndex(parameterName), parameterValue); + } + + /** + Tests if a DataTruncation occurred on the read of a piece of + data and posts a DataTruncation warning if so. + + @param parameterIndex The parameter index (1-based). + @param data The data that was read, or null for SQL NULL. + @param exceptionOnTrunc Flag to notify method whether or not to throw an SQLException when there is truncation. + numeric types should always throw exception on truncation. This was added because + we now support getMethods for compatible types. + **/ + private void testDataTruncation(int parameterIndex, SQLData data, boolean exceptionOnTrunc) throws SQLException + { + if(wasDataMappingError_) + { + postWarning(new DataTruncation(parameterIndex, true, true, -1, -1)); + } + + if(data != null) + { + int truncated = data.getTruncated(); + + if(truncated > 0) + { + if((exceptionOnTrunc == true)) { //@trunc + if (data.getOutOfBounds()) { + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); //@trunc + } + } //@trunc + int actualSize = data.getActualSize(); + postWarning(new DataTruncation(parameterIndex, true, true, actualSize, actualSize - truncated)); + } + } + } + + //@pdd jdbc40 move method to preparedStatement + //@pdd private static final String unquote(String name) + //@pdd { + //@pdd return JDUtilities.prepareForSingleQuotes(name, true); + //@pdd } + + //@pdd jdbc40 move methodto preparedStatement + //@pdd private static final String unquoteNoUppercase(String name) + //@pdd { + //@pdd return JDUtilities.prepareForSingleQuotes(name, false); + //@pdd } + + /** + Indicates if the last parameter read has the + value of SQL NULL. + + @return true if the value is SQL NULL; + false otherwise. + + @exception SQLException If the statement is not open. + **/ + public boolean wasNull() + throws SQLException + { + synchronized(internalLock_) + { // @E1A + checkOpen(); + return wasNull_; + } + } + + + //@pda jdbc40 + protected String[] getValidWrappedList() + { + return new String[] { "com.ibm.as400.access.AS400JDBCCallableStatement", "java.sql.CallableStatement" }; + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated parameter as a + * java.io.Reader object in the Java programming language. + * + * @return a java.io.Reader object that contains the parameter + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language. + * @param parameterIndex the first parameter is 1, the second is 2, ... + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + */ + public Reader getCharacterStream(int parameterIndex) throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Reader value = (data == null) ? null : data.getCharacterStream(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated parameter as a + * java.io.Reader object in the Java programming language. + * + * @param parameterName the name of the parameter + * @return a java.io.Reader object that contains the parameter + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public Reader getCharacterStream(String parameterName) throws SQLException + { + return getCharacterStream(findParameterIndex(parameterName)); + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated parameter as a + * java.io.Reader object in the Java programming language. + * It is intended for use when + * accessing NCHAR,NVARCHAR + * and LONGNVARCHAR parameters. + * + * @return a java.io.Reader object that contains the parameter + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language. + * @param parameterIndex the first parameter is 1, the second is 2, ... + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public Reader getNCharacterStream(int parameterIndex) throws SQLException + { + + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + Reader value = (data == null) ? null : data.getNCharacterStream(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated parameter as a + * java.io.Reader object in the Java programming language. + * It is intended for use when + * accessing NCHAR,NVARCHAR + * and LONGNVARCHAR parameters. + * + * @param parameterName the name of the parameter + * @return a java.io.Reader object that contains the parameter + * value; if the value is SQL NULL, the value returned is + * null in the Java programming language + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public Reader getNCharacterStream(String parameterName) throws SQLException + { + return getNCharacterStream(findParameterIndex(parameterName)); + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated JDBC NCLOB parameter as a + * java.sql.NClob object in the Java programming language. + * + * @param parameterIndex the first parameter is 1, the second is 2, and + * so on + * @return the parameter value as a NClob object in the + * Java programming language. If the value was SQL NULL, the + * value null is returned. + * @exception SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public NClob getNClob(int parameterIndex) throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // make sure the registered type is valid for this get method + switch(registeredTypes_[parameterIndex-1]) { + case Types.CLOB: + case Types.NCLOB : + case Types.JAVA_OBJECT: + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + NClob value = (data == null) ? null : data.getNClob(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } +/* endif */ + + //@PDA jdbc40 + /** + * Retrieves the value of a JDBC NCLOB parameter as a + * java.sql.NClob object in the Java programming language. + * @param parameterName the name of the parameter + * @return the parameter value as a NClob object in the + * Java programming language. If the value was SQL NULL, + * the value null is returned. + * @exception SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public NClob getNClob(String parameterName) throws SQLException + { + return getNClob(findParameterIndex(parameterName)); + } +/* endif */ + + //@PDA jdbc40 + /** + * Retrieves the value of the designated NCHAR, + * NVARCHAR + * or LONGNVARCHAR parameter as + * a String in the Java programming language. + *

+ * For the fixed-length type JDBC NCHAR, + * the String object + * returned has exactly the same value the SQL + * NCHAR value had in the + * database, including any padding added by the database. + * + * @param parameterIndex index of the first parameter is 1, the second is 2, ... + * @return a String object that maps an + * NCHAR, NVARCHAR or LONGNVARCHAR value + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @see #setNString + */ + public String getNString(int parameterIndex) throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + String value = (data == null) ? null : data.getNString(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated NCHAR, + * NVARCHAR + * or LONGNVARCHAR parameter as + * a String in the Java programming language. + *

+ * For the fixed-length type JDBC NCHAR, + * the String object + * returned has exactly the same value the SQL + * NCHAR value had in the + * database, including any padding added by the database. + * + * @param parameterName the name of the parameter + * @return a String object that maps an + * NCHAR, NVARCHAR or LONGNVARCHAR value + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @see #setNString + */ + public String getNString(String parameterName) throws SQLException + { + return getNString(findParameterIndex(parameterName)); + } + + //@PDA jdbc40 + /** + * Retrieves the value of the designated JDBC ROWID parameter as a + * java.sql.RowId object. + * + * @param parameterIndex the first parameter is 1, the second is 2,... + * @return a RowId object that represents the JDBC ROWID + * value is used as the designated parameter. If the parameter contains + * a SQL NULL, then a null value is returned. + * @throws SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public RowId getRowId(int parameterIndex) throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(!parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + RowId value = (data == null) ? null : data.getRowId(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } +/* endif */ + + //@PDA jdbc40 + /** + * Retrieves the value of the designated JDBC ROWID parameter as a + * java.sql.RowId object. + * + * @param parameterName the name of the parameter + * @return a RowId object that represents the JDBC ROWID + * value is used as the designated parameter. If the parameter contains + * a SQL NULL, then a null value is returned. + * @throws SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public RowId getRowId(String parameterName) throws SQLException + { + return getRowId(findParameterIndex(parameterName)); + } +/* endif */ + + //@PDA jdbc40 + /** + * Retrieves the value of the designated SQL XML parameter as a + * java.sql.SQLXML object in the Java programming language. + * @param parameterIndex index of the first parameter is 1, the second is 2, ... + * @return a SQLXML object that maps an SQL XML value + * @throws SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public SQLXML getSQLXML(int parameterIndex) throws SQLException + { + synchronized(internalLock_) + { + checkOpen(); + + SQLData data = null; + + // Check if the parameter index refers to the return value parameter. + // If it is not parameter index 1, then decrement the parameter index, + // since we are "faking" the return value parameter. + if(useReturnValueParameter_ && parameterIndex == 1) + { + if(!returnValueParameterRegistered_) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + data = returnValueParameter_; + } + else + { + if(useReturnValueParameter_) + { + --parameterIndex; + } + + // Validate the parameter index. + if((parameterIndex < 1) || (parameterIndex > parameterCount_)) + JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID); + + // Check that the parameter is an output parameter. + if(! parameterRow_.isOutput(parameterIndex)) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Verify that the output parameter is registered. + if(registered_[parameterIndex-1] == false) + JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); + + // Get the data and check for SQL NULL. + data = getValue(parameterIndex); + } + + SQLXML value = (data == null) ? null : data.getSQLXML(); + testDataTruncation(parameterIndex, data, false); + return value; + } + } +/* endif */ + + //@PDA jdbc40 + /** + * Retrieves the value of the designated SQL XML parameter as a + * java.sql.SQLXML object in the Java programming language. + * @param parameterName the name of the parameter + * @return a SQLXML object that maps an SQL XML value + * @throws SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public SQLXML getSQLXML(String parameterName) throws SQLException + { + return getSQLXML(findParameterIndex(parameterName)); + } +/* endif */ + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given input stream, which will have + * the specified number of bytes. + * When a very large ASCII value is input to a LONGVARCHAR + * parameter, it may be more practical to send it via a + * java.io.InputStream. Data will be read from the stream + * as needed until end-of-file is reached. The JDBC driver will + * do any necessary conversion from ASCII to the database char format. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + * + * @param parameterName the name of the parameter + * @param x the Java input stream that contains the ASCII parameter value + * @param length the number of bytes in the stream + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setAsciiStream()"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setAsciiStream(findParameterIndex(parameterName), x, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given input stream, which will have + * the specified number of bytes. + * When a very large binary value is input to a LONGVARBINARY + * parameter, it may be more practical to send it via a + * java.io.InputStream object. The data will be read from the stream + * as needed until end-of-file is reached. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + * + * @param parameterName the name of the parameter + * @param x the java input stream which contains the binary parameter value + * @param length the number of bytes in the stream + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method. + */ + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setBinaryStream()"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setBinaryStream(findParameterIndex(parameterName), x, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given java.sql.Blob object. + * The driver converts this to an SQL BLOB value when it + * sends it to the database. + * + * @param parameterName the name of the parameter + * @param x a Blob object that maps an SQL BLOB value + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setBlob(String parameterName, Blob x) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setBlob()"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + x.length()); + } + + setBlob(findParameterIndex(parameterName), x); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a InputStream object. The InputStream must contain the number + * of characters specified by length, otherwise a SQLException will be + * generated when the CallableStatement is executed. + * This method differs from the setBinaryStream (int, InputStream, int) + * method because it informs the driver that the parameter value should be + * sent to the system as a BLOB. When the setBinaryStream method is used, + * the driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGVARBINARY or a BLOB + * + * @param parameterName the name of the parameter to be set + * + * @param inputStream An object that contains the data to set the parameter + * value to. + * @param length the number of bytes in the parameter data. + * @throws SQLException if parameterIndex does not correspond + * to a parameter marker in the SQL statement, or if the length specified + * is less than zero; if the number of bytes in the inputStream does not match + * the specfied length; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * + */ + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setBlob()"); + if(inputStream == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setBlob(findParameterIndex(parameterName), inputStream, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given Reader + * object, which is the given number of characters long. + * When a very large UNICODE value is input to a LONGVARCHAR + * parameter, it may be more practical to send it via a + * java.io.Reader object. The data will be read from the stream + * as needed until end-of-file is reached. The JDBC driver will + * do any necessary conversion from UNICODE to the database char format. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + * + * @param parameterName the name of the parameter + * @param reader the java.io.Reader object that + * contains the UNICODE data used as the designated parameter + * @param length the number of characters in the stream + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setCharacterStream()"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setCharacterStream(findParameterIndex(parameterName), reader, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given java.sql.Clob object. + * The driver converts this to an SQL CLOB value when it + * sends it to the database. + * + * @param parameterName the name of the parameter + * @param x a Clob object that maps an SQL CLOB value + * @exception SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setClob(String parameterName, Clob x) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setClob()"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + x.length()); + } + + setClob(findParameterIndex(parameterName), x); + + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. The reader must contain the number + * of characters specified by length otherwise a SQLException will be + * generated when the CallableStatement is executed. + * This method differs from the setCharacterStream (int, Reader, int) method + * because it informs the driver that the parameter value should be sent to + * the system as a CLOB. When the setCharacterStream method is used, the + * driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGVARCHAR or a CLOB + * @param parameterName the name of the parameter to be set + * @param reader An object that contains the data to set the parameter value to. + * @param length the number of characters in the parameter data. + * @throws SQLException if parameterIndex does not correspond to a parameter + * marker in the SQL statement; if the length specified is less than zero; + * a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * + */ + public void setClob(String parameterName, Reader reader, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setClob()"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setClob(findParameterIndex(parameterName), reader, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. The + * Reader reads the data till end-of-file is reached. The + * driver does the necessary conversion from Java character format to + * the national character set in the database. + * @param parameterName the name of the parameter to be set + * @param value the parameter value + * @param length the number of characters in the parameter data. + * @throws SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNCharacterStream()"); + if(value == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setNCharacterStream(findParameterIndex(parameterName), value, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a java.sql.NClob object. The object + * implements the java.sql.NClob interface. This NClob + * object maps to a SQL NCLOB. + * @param parameterName the name of the parameter to be set + * @param value the parameter value + * @throws SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public void setNClob(String parameterName, NClob value) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNClob()"); + if(value == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + value.length()); + } + + setNClob(findParameterIndex(parameterName), value); + } +/* endif */ + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. The reader must contain the number + * of characters specified by length otherwise a SQLException will be + * generated when the CallableStatement is executed. + * This method differs from the setCharacterStream (int, Reader, int) method + * because it informs the driver that the parameter value should be sent to + * the system as a NCLOB. When the setCharacterStream method is used, the + * driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGNVARCHAR or a NCLOB + * + * @param parameterName the name of the parameter to be set + * @param reader An object that contains the data to set the parameter value to. + * @param length the number of characters in the parameter data. + * @throws SQLException if parameterIndex does not correspond to a parameter + * marker in the SQL statement; if the length specified is less than zero; + * if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setNClob(String parameterName, Reader reader, long length) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNClob()"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + length); + } + + setNClob(findParameterIndex(parameterName), reader, length); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given String object. + * The driver converts this to a SQL NCHAR or + * NVARCHAR or LONGNVARCHAR + * @param parameterName the name of the parameter to be set + * @param value the parameter value + * @throws SQLException if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ + public void setNString(String parameterName, String value) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNString()"); + if(value == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else if(value.length() > maxToLog_) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + value.length()); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + value); + } + + setNString(findParameterIndex(parameterName), value); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given java.sql.RowId object. The + * driver converts this to a SQL ROWID when it sends it to the + * database. + * + * @param parameterName the name of the parameter + * @param x the parameter value + * @throws SQLException if a database access error occurs or + * this method is called on a closed CallableStatement + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public void setRowId(String parameterName, RowId x) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setRowId()"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: " + x.toString()); + } + + setRowId(findParameterIndex(parameterName), x); + } +/* endif */ + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given java.sql.SQLXML object. The driver converts this to an + * SQL XML value when it sends it to the database. + * + * @param parameterName the name of the parameter + * @param xmlObject a SQLXML object that maps an SQL XML value + * @throws SQLException if a database access error occurs, + * this method is called on a closed CallableStatement or + * the java.xml.transform.Result, + * Writer or OutputStream has not been closed for the SQLXML object + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + */ +/* ifdef JDBC40 */ + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setClob()"); + if(xmlObject == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + else JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " length: " + xmlObject.toString().length()); + } + + setSQLXML(findParameterIndex(parameterName), xmlObject); + } +/* endif */ + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given input stream. + * When a very large ASCII value is input to a LONGVARCHAR + * parameter, it may be more practical to send it via a + * java.io.InputStream. Data will be read from the stream + * as needed until end-of-file is reached. The JDBC driver will + * do any necessary conversion from ASCII to the database char format. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setAsciiStream which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param x the Java input stream that contains the ASCII parameter value + * @exception SQLException if parameterName does not correspond to a named + * parameter; if a database access error occurs or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setAsciiStream(String parameterName, InputStream x) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setAsciiStream(String, InputStream)"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setAsciiStream(findParameterIndex(parameterName), x); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given input stream. + * When a very large binary value is input to a LONGVARBINARY + * parameter, it may be more practical to send it via a + * java.io.InputStream object. The data will be read from the + * stream as needed until end-of-file is reached. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setBinaryStream which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param x the java input stream which contains the binary parameter value + * @exception SQLException if parameterName does not correspond to a named + * parameter; if a database access error occurs or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setBinaryStream(String parameterName, InputStream x) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setBinaryStream(String, InputStream)"); + if(x == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setBinaryStream(findParameterIndex(parameterName), x); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a InputStream object. + * This method differs from the setBinaryStream (int, InputStream) + * method because it informs the driver that the parameter value should be + * sent to the system as a BLOB. When the setBinaryStream method is used, + * the driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGVARBINARY or a BLOB + * + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setBlob which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param inputStream An object that contains the data to set the parameter + * value to. + * @throws SQLException if parameterName does not correspond to a named + * parameter; if a database access error occurs or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setBlob(String parameterName, InputStream inputStream) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setBlob(String, InputStream)"); + if(inputStream == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setBlob(findParameterIndex(parameterName), inputStream); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to the given Reader + * object. + * When a very large UNICODE value is input to a LONGVARCHAR + * parameter, it may be more practical to send it via a + * java.io.Reader object. The data will be read from the stream + * as needed until end-of-file is reached. The JDBC driver will + * do any necessary conversion from UNICODE to the database char format. + * + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setCharacterStream which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param reader the java.io.Reader object that contains the + * Unicode data + * @exception SQLException if parameterName does not correspond to a named + * parameter; if a database access error occurs or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setCharacterStream(String parameterName, Reader reader) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setCharacterStream(String, Reader)"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setCharacterStream(findParameterIndex(parameterName), reader); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. + * This method differs from the setCharacterStream (int, Reader) method + * because it informs the driver that the parameter value should be sent to + * the system as a CLOB. When the setCharacterStream method is used, the + * driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGVARCHAR or a CLOB + * + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setClob which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param reader An object that contains the data to set the parameter value to. + * @throws SQLException if parameterName does not correspond to a named + * parameter; if a database access error occurs or this method is called on + * a closed CallableStatement + * + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setClob(String parameterName, Reader reader) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setClob(String, Reader)"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setClob(findParameterIndex(parameterName), reader); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. The + * Reader reads the data till end-of-file is reached. The + * driver does the necessary conversion from Java character format to + * the national character set in the database. + + *

Note: This stream object can either be a standard + * Java stream object or your own subclass that implements the + * standard interface. + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setNCharacterStream which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param value the parameter value + * @throws SQLException if parameterName does not correspond to a named + * parameter; if the driver does not support national + * character sets; if the driver can detect that a data conversion + * error could occur; if a database access error occurs; or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + */ + public void setNCharacterStream(String parameterName, Reader value) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNCharacterStream(String, Reader)"); + if(value == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setNCharacterStream(findParameterIndex(parameterName), value); + } + + //@PDA jdbc40 + /** + * Sets the designated parameter to a Reader object. + * This method differs from the setCharacterStream (int, Reader) method + * because it informs the driver that the parameter value should be sent to + * the system as a NCLOB. When the setCharacterStream method is used, the + * driver may have to do extra work to determine whether the parameter + * data should be sent to the system as a LONGNVARCHAR or a NCLOB + *

Note: Consult your JDBC driver documentation to determine if + * it might be more efficient to use a version of + * setNClob which takes a length parameter. + * + * @param parameterName the name of the parameter + * @param reader An object that contains the data to set the parameter value to. + * @throws SQLException if parameterName does not correspond to a named + * parameter; if the driver does not support national character sets; + * if the driver can detect that a data conversion + * error could occur; if a database access error occurs or + * this method is called on a closed CallableStatement + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method + * + */ + public void setNClob(String parameterName, Reader reader) throws SQLException + { + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "setNClob(String, Reader)"); + if(reader == null) + JDTrace.logInformation(this, "parameter index: " + findParameterIndex(parameterName) + " value: NULL"); + } + + setNClob(findParameterIndex(parameterName), reader); + } + + + public Object getObject(int parameterIndex, Class type) + throws SQLException { + // Throw exception if type is null + if (type == null) { + JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID); + } + if (byteArrayClass_ == null) { + byte[] byteArray = new byte[1]; + byteArrayClass_ = byteArray.getClass(); + } + // Use the appropriate method to get the correct data type. + // After checking for string, we check for classes in the + // order specified in Table B-6 of the JDBC 4.0 specification + // + if (type == java.lang.String.class ) { + return getString(parameterIndex); + } else if (type == java.lang.Byte.class){ + byte b = getByte(parameterIndex); + if (b == 0 && wasNull()) { + return null; + } else { + return new Byte(b); + } + } else if (type == java.lang.Short.class){ + short s = getShort(parameterIndex); + if (s == 0 && wasNull()) { + return null; + } else { + return new Short(s); + } + } else if (type == java.lang.Integer.class){ + int i = getInt(parameterIndex); + if (i == 0 && wasNull()) { + return null; + } else { + return new Integer(i); + } + } else if (type == java.lang.Long.class){ + long l = getLong(parameterIndex); + if (l == 0 && wasNull()) { + return null; + } else { + return new Long(l); + } + } else if (type == java.lang.Float.class){ + float f = getFloat(parameterIndex); + if (f == 0 && wasNull()) { + return null; + } else { + return new Float(f); + } + } else if (type == java.lang.Double.class){ + double d = getDouble(parameterIndex); + if (d == 0 && wasNull()) { + return null; + } else { + return new Double(d); + } + } else if (type == java.math.BigDecimal.class){ + return getBigDecimal(parameterIndex); + } else if (type == java.lang.Boolean.class) { + boolean b = getBoolean(parameterIndex); + if (b == false && wasNull()) { + return null; + } else { + return new Boolean (b); + } + + } else if (type == java.sql.Date.class){ + return getDate(parameterIndex); + } else if (type == java.sql.Time.class){ + return getTime(parameterIndex); + } else if (type == java.sql.Timestamp.class){ + return getTimestamp(parameterIndex); + } else if (type == byteArrayClass_){ + return getBytes(parameterIndex); + } else if (type == InputStream.class){ + Blob b = getBlob(parameterIndex); + if (b == null) { + return b; + } else { + return b.getBinaryStream(); + } + } else if (type == Reader.class){ + return getCharacterStream(parameterIndex); + } else if (type == Clob.class){ + return getClob(parameterIndex); + } else if (type == Blob.class){ + return getBlob(parameterIndex); + } else if (type == Array.class){ + return getArray(parameterIndex); + } else if (type == Ref.class){ + return getRef(parameterIndex); + } else if (type == URL.class){ + return getURL(parameterIndex); +/* ifdef JDBC40 */ + } else if (type == NClob.class){ + return getNClob(parameterIndex); + } else if (type == RowId.class){ + return getRowId(parameterIndex); + } else if (type == SQLXML.class){ + return getSQLXML(parameterIndex); +/* endif */ + } else if (type == Object.class){ + return getObject(parameterIndex); + } + + JDError.throwSQLException (JDError.EXC_DATA_TYPE_INVALID); + return null; + } + + public Object getObject(String parameterName, Class type) + throws SQLException { + return getObject(findParameterIndex(parameterName), type); + } + + /* + * Validate that the registered type is valid for getNumeric type conversions. + * Previously, getInt, ...., could only get used against a type registered as INT. + * @param registeredType + */ + private void validateNumericRegisteredType(int registeredType) throws SQLException { + // make sure the registered type is valid for this get method + // Assuming that the compatibility should be the same as the get methods, + // the following registered types are allowed. + // Updated 9/29/2011 as part of JDBC 4.1 updates to allow getObject(x,java.lang.Integer) to work. + switch(registeredType) { + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + case Types.DECIMAL: + case Types.NUMERIC: + case Types.BIT: + case Types.BOOLEAN: + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.JAVA_OBJECT: + /* types are good */ + break; + default: + JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); + } + } + + + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCClob.java b/jdbc40/com/ibm/as400/access/AS400JDBCClob.java new file mode 100644 index 000000000..e755e9819 --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCClob.java @@ -0,0 +1,529 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCClob.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; + +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.io.CharArrayReader; +import java.sql.Clob; +import java.sql.SQLException; + +// Note: This code in this class requires understanding of bit manipulation +// and sign extension. Do not attempt to rework this code if you do not +// have a grasp of these concepts. + +// Currently, the database host server only supports 2 GB LOBs. Therefore, +// we validate any long parameters to make sure they are not greater than +// the maximum positive value for a 4-byte int (2 GB). This has the added +// bonus of being able to cast the long down to an int without worrying +// about sign extension. There are some cases where we could allow the +// user to pass in a long greater than 2 GB, but for consistency, we will +// throw an exception. + +// Offset refers to a 0-based index. Position refers to a 1-based index. + + +/** +The AS400JDBCClob class provides access to character large +objects. The data is valid only within the current +transaction. +**/ +public class AS400JDBCClob implements Clob +{ + static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others."; + + protected char[] data_; //@pdc jdbc40 + protected int maxLength_; //@pdc jdbc40 + static final int MAX_LOB_SIZE = 2147483647; //@PDA jdbc40 same as native driver. (if column is a DBCLOB the limit is 1,073,741,823) + private boolean isXML_ = false; //@xmltrim true if this data originated from a native XML column type + +/** +Constructs an AS400JDBCClob object. The data is contained +in the String. No further communication with the IBM i system is necessary. + +@param data The CLOB data. +**/ + AS400JDBCClob(String data, int maxLength) + { + data_ = data.toCharArray(); + maxLength_ = maxLength; + } + + AS400JDBCClob(String data) + { + data_ = data.toCharArray(); + maxLength_ = MAX_LOB_SIZE; + } + + + AS400JDBCClob(char[] data) + { + data_ = data; + maxLength_ = MAX_LOB_SIZE; + } + + //@xmltrim + /** + Constructs an AS400JDBCClob object. The data is contained + in the String. No further communication with the IBM i system is necessary. + If this clob has a source of a columne of type XML, then any getX method that returns xml as string will trim the xml declaration. + + @param data The CLOB data. + @param maxLength + @param isXML flag to signal if source is xml + **/ + AS400JDBCClob(String data, int maxLength, boolean isXML) + { + data_ = data.toCharArray(); + maxLength_ = maxLength; + isXML_ = isXML; + } + + //@xmltrim + AS400JDBCClob(char[] data, boolean isXML) + { + data_ = data; + isXML_ = isXML; + } + + + +/** +Returns the entire CLOB as a stream of ASCII characters. + +@return The stream. + +@exception SQLException If an error occurs. +**/ + public synchronized InputStream getAsciiStream() throws SQLException + { + //Following Native, throw HY010 after free() has been called + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + try + { + if(isXML_)//@xmltrim + return new ByteArrayInputStream((JDUtilities.stripXMLDeclaration(new String(data_))).getBytes("ISO8859_1")); //@xmltrim + else + return new ByteArrayInputStream((new String(data_)).getBytes("ISO8859_1")); + } + catch (UnsupportedEncodingException e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + } + + + +/** +Returns the entire CLOB as a character stream. + +@return The stream. + +@exception SQLException If an error occurs. +**/ + public synchronized Reader getCharacterStream() throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if(isXML_)//@xmltrim + return new CharArrayReader( JDUtilities.stripXMLDeclaration( new String(data_) ).toCharArray()); //@xmltrim + else + return new CharArrayReader(data_); + } + + + +/** +Returns part of the contents of the CLOB. + +@param position The start position within the CLOB (1-based). +@param length The length to return. +@return The contents. + +@exception SQLException If the start position is not valid, + if the length is not valid, + or an error occurs. +**/ + public synchronized String getSubString(long position, int length) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + // Only throw exception if offset if greater than the length + // It is valid for the requested length to be greater than the actual length + // @J5C + if (offset < 0 || length < 0 || (offset > data_.length)) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + //@xmltrim + if(isXML_) + { + data_ = JDUtilities.stripXMLDeclaration( new String(data_) ).toCharArray(); + } + + int lengthToUse = data_.length - offset; + if (lengthToUse <= 0) return ""; + if (lengthToUse > length) lengthToUse = length; + + char[] result = new char[lengthToUse]; + System.arraycopy(data_, offset, result, 0, lengthToUse); + return new String(result); + } + + + +/** +Returns the length of the CLOB. + +@return The length of the CLOB, in characters. + +@exception SQLException If an error occurs. +**/ + public synchronized long length() throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + return data_.length; + } + + + +/** +Returns the position at which a pattern is found in the CLOB. + +@param pattern The pattern. +@param position The position within the CLOB to begin + searching (1-based). +@return The position at which the pattern + is found, or -1 if the pattern is not + found. + +@exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. +**/ + public synchronized long position(String pattern, long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= data_.length) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } else { + + char[] charPattern = pattern.toCharArray(); + int end = data_.length - charPattern.length; + + for (int i=offset; i<=end; ++i) + { + int j = 0; + while (j < charPattern.length && data_[i+j] == charPattern[j]) ++j; + if (j == charPattern.length) return i+1; + } + } + return -1; + + } + + + +/** +Returns the position at which a pattern is found in the CLOB. + +@param pattern The pattern. +@param position The position within the CLOB to begin + searching (1-based). +@return The position at which the pattern + is found, or -1 if the pattern is not + found. + +@exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. +**/ + public synchronized long position(Clob pattern, long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= data_.length) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } else { + + int patternLength = (int)pattern.length(); + if (patternLength > data_.length || patternLength < 0) return -1; + + int end = data_.length - patternLength; + + char[] charPattern = pattern.getSubString(1L, patternLength).toCharArray(); //@CRS - Get all the chars for now, improve this later. + + for (int i=offset; i<=end; ++i) + { + int j = 0; + while (j < charPattern.length && data_[i+j] == charPattern[j]) ++j; + if (j == charPattern.length) return i+1; + } + } + return -1; + } + + + /** + Returns a stream that an application can use to write Ascii characters to this CLOB. + The stream begins at position position, and the CLOB will be truncated + after the last character of the write. + + @param position The position (1-based) in the CLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + **/ + public OutputStream setAsciiStream(long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + try + { + return new AS400JDBCClobOutputStream(this, position, ConvTable.getTable(819, null)); + } + catch (UnsupportedEncodingException e) + { + // Should never happen. + JDError.throwSQLException(JDError.EXC_INTERNAL, e); + return null; + } + } + + + + /** + Returns a stream that an application can use to write a stream of Unicode characters to + this CLOB. The stream begins at position position, and the CLOB will + be truncated after the last character of the write. + + @param position The position (1-based) in the CLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + **/ + public synchronized Writer setCharacterStream(long position) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + return new AS400JDBCWriter(this, position); + } + + + + /** + Writes a String to this CLOB, starting at position position. The CLOB + will be truncated after the last character written. + + @param position The position (1-based) in the CLOB where writes should start. + @param stringToWrite The string that will be written to the CLOB. + @return The number of characters that were written. + + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + **/ + public synchronized int setString(long position, String stringToWrite) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int offset = (int)position-1; + + if (offset < 0 || offset >= maxLength_ || stringToWrite == null) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many chars as we can. If our internal char array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of chars that were set. + char[] charsToWrite = stringToWrite.toCharArray(); + int newSize = offset + charsToWrite.length; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + if (newSize > data_.length) + { + char[] temp = data_; + data_ = new char[newSize]; + System.arraycopy(temp, 0, data_, 0, temp.length); + int numPad = offset - temp.length; //Determine if we need to Pad with single byte space before we write the new data_ @K1A + //the number of spaces we need to pad is equal to the offset we want to start writing at minus the length of the current clob(temp) @K1A + for(int i=0; iposition in the CLOB. + The CLOB will be truncated after the last character written. The lengthOfWrite + characters written will start from offset in the string that was provided by the + application. + + @param position The position (1-based) in the CLOB where writes should start. + @param string The string that will be written to the CLOB. + @param offset The offset into string to start reading characters (0-based). + @param lengthOfWrite The number of characters to write. + @return The number of characters written. + + @exception SQLException If there is an error accessing the CLOB value or if the position + specified is greater than the length of the CLOB. + **/ + public synchronized int setString(long position, String string, int offset, int lengthOfWrite) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int clobOffset = (int)position-1; + if (clobOffset < 0 || clobOffset >= maxLength_ || + string == null || offset < 0 || lengthOfWrite < 0 || (offset+lengthOfWrite) > string.length() || + (clobOffset+lengthOfWrite) > maxLength_) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many chars as we can. If our internal char array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of chars that were set. + char[] charsToWrite = string.toCharArray(); + int newSize = clobOffset + lengthOfWrite; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + if (newSize > data_.length) + { + char[] temp = data_; + data_ = new char[newSize]; + System.arraycopy(temp, 0, data_, 0, temp.length); + int numPad = offset - temp.length; //Determine if we need to Pad with single byte space before we write the new data_ @K1A + //the number of spaces we need to pad is equal to the offset we want to start writing at minus the length of the current clob(temp) @K1A + for(int i=0; ilengthOfCLOB characters. + + @param lengthOfCLOB The length, in characters, that this CLOB should be after + truncation. + + @exception SQLException If there is an error accessing the CLOB or if the length + specified is greater than the length of the CLOB. + **/ + public synchronized void truncate(long lengthOfCLOB) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + int length = (int)lengthOfCLOB; + if (length < 0 || length > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + char[] temp = data_; + data_ = new char[length]; + int numToCopy = length < temp.length ? length : temp.length; + System.arraycopy(temp, 0, data_, 0, numToCopy); + } + + // @PDA jdbc40 + /** + * This method frees the Clob object and releases the + * resources the resources that it holds. The object is invalid once the + * free method is called. If free is called + * multiple times, the subsequent calls to free are treated + * as a no-op. + * + * @throws SQLException + * if an error occurs releasing the Clob's resources + */ + public synchronized void free() throws SQLException + { + data_ = null; //@pda make available for GC + } + + // @PDA jdbc40 + /** + * Returns a Reader object that contains a partial + * Clob value, starting with the character specified by pos, + * which is length characters in length. + * + * @param pos + * the offset to the first character of the partial value to be + * retrieved. The first character in the Clob is at position 1. + * @param length + * the length in characters of the partial value to be retrieved. + * @return Reader through which the partial Clob + * value can be read. + * @throws SQLException + * if pos is less than 1 or if pos is greater than the number of + * characters in the Clob or if pos + length is + * greater than the number of characters in the + * Clob + */ + public synchronized Reader getCharacterStream(long pos, long length) throws SQLException + { + if(data_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if(isXML_ )//@xmltrim + return new CharArrayReader( JDUtilities.stripXMLDeclaration( new String(data_)).toCharArray(), (int) pos-1, (int)length); //@xmltrim + else + return new CharArrayReader(data_, (int) pos-1, (int)length); + } + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCClobLocator.java b/jdbc40/com/ibm/as400/access/AS400JDBCClobLocator.java new file mode 100644 index 000000000..da20b337c --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCClobLocator.java @@ -0,0 +1,678 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCClobLocator.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.IOException; +import java.io.InputStream; + +import java.io.OutputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.sql.Clob; +import java.sql.SQLException; + + +// Note: This code in this class requires understanding of bit manipulation +// and sign extension. Do not attempt to rework this code if you do not +// have a grasp of these concepts. + +// Currently, the database host server only supports 2 GB LOBs. Therefore, +// we validate any long parameters to make sure they are not greater than +// the maximum positive value for a 4-byte int (2 GB). This has the added +// bonus of being able to cast the long down to an int without worrying +// about sign extension. There are some cases where we could allow the +// user to pass in a long greater than 2 GB, but for consistency, we will +// throw an exception. + +// Offset refers to a 0-based index. Position refers to a 1-based index. + +// In the event that the column in the database is a DBCLOB, know that +// JDLobLocator knows that it is graphic and will correctly convert +// the byte offsets and lengths into character offsets and lengths. + +// For the case where the column has a CCSID with variable size +// characters, all the data will be needed to be retrieved and +// translated for request requiring the length of the lob, as +// well as for requests requiring a character offset into the lob. + + +/** +The AS400JDBCClobLocator class provides access to character large +objects. The data is valid only within the current +transaction. +**/ +public class AS400JDBCClobLocator implements Clob +{ + protected ConvTable converter_; //@pdc jdbc40 + JDLobLocator locator_; + + Object savedObject_; // This is our InputStream or byte[] or whatever that needs to be written if we are batching. + int savedScale_; // This is our length that goes with our savedObject_. + + private char[] cache_; + private int cacheOffset_; + private static final char[] INIT_CACHE = new char[0]; + + //private int truncate_ = -1; + protected int maxLength_; // The max length in LOB-characters. See JDLobLocator. //@pdc jdbc40 + private boolean isXML_ = false; //@xml3 true if this data originated from a native XML column type + + /** + Constructs an AS400JDBCClobLocator object. The data for the + CLOB will be retrieved as requested, directly from the + IBM i system, using the locator handle. + + @param locator The locator. + @param converter The text converter. + **/ + AS400JDBCClobLocator(JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale) + { + locator_ = locator; + converter_ = converter; + savedObject_ = savedObject; + savedScale_ = savedScale; + maxLength_ = locator_.getMaxLength(); + } + + //@xml3 new constructor + /** + Constructs an AS400JDBCClobLocator object. The data for the + CLOB will be retrieved as requested, directly from the + IBM i system, using the locator handle. + If this clob has a source of a columne of type XML, then any getX method that returns xml as string will trim the xml declaration. + + @param locator The locator. + @param converter The text converter. + @param savedObject Input data + @param savedScale Inpuat scale of data + @param isXML Flag that stream is from an XML column type (needed to strip xml declaration) + **/ + AS400JDBCClobLocator(JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale, boolean isXML) + { + this(locator, converter, savedObject, savedScale); + isXML_ = isXML; + } + + + /** + Returns the entire CLOB as a stream of ASCII characters. + + @return The stream. + + @exception SQLException If an error occurs. + **/ + public InputStream getAsciiStream() throws SQLException + { + //Following Native, throw HY010 after free() has been called. Note: NullPointerException if synchronized(null-ref) + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + try + { + //@xml3 if xml column, remove xml declaration via ConvTableReader + return new ReaderInputStream(new ConvTableReader(new AS400JDBCInputStream(locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_), 819); // ISO 8859-1. //@xml3 + } + catch (UnsupportedEncodingException e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + } + } + + + + /** + Returns the entire CLOB as a character stream. + + @return The stream. + + @exception SQLException If an error occurs. + **/ + public Reader getCharacterStream() throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + try + { + //@xml3 if xml column, remove xml declaration via ConvTableReader + return new ConvTableReader(new AS400JDBCInputStream(locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_); //@xml3 + } + catch (UnsupportedEncodingException e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + } + } + + + +/** +Returns the handle to this CLOB locator in the database. + +@return The handle to this locator in the databaes. +**/ + int getHandle()throws SQLException //@free called from rs.updateValue(), which in turn will throw exc back to rs.updateX() caller + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + return locator_.getHandle(); + } + + + + /** + Returns part of the contents of the CLOB. + + @param position The position within the CLOB (1-based). + @param length The number of characters to return. + @return The contents. + + @exception SQLException If the position is not valid, + if the length is not valid, + or an error occurs. + **/ + public String getSubString(long position, int length) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (offset < 0 || length < 0 || (offset > length()) ) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int lengthToUse = (int)length() - offset; + if (lengthToUse < 0) return ""; + if (lengthToUse > length) lengthToUse = length; + + + + //@xml4 if xml column, remove xml declaration via ConvTableReader + if(isXML_) + { + ConvTableReader r = null; + try{ + r = new ConvTableReader(new AS400JDBCInputStream( locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_); //@xml4 + r.skip(offset); //@xml4 ConvTableReader will already have skipped XML header if column is XML type + return r.read(lengthToUse); //@xml4 + } + catch ( Exception e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + finally{ + try{ + if (r != null ) r.close(); + }catch(Exception ee){ + JDTrace.logException(this, "getSubString r.close() threw exception", ee); + } + } + } + + DBLobData data = locator_.retrieveData(offset, lengthToUse); + int actualLength = data.getLength(); + return converter_.byteArrayToString(data.getRawBytes(), data.getOffset(), actualLength); + } + } + + + + /** + Returns the length of the current contents of the CLOB in characters. + + @return The length of the CLOB in characters. + + @exception SQLException If an error occurs. + **/ + public long length() throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + return locator_.getLength(); + } + } + + + // Used for position(). + private void initCache() + { + cacheOffset_ = 0; + cache_ = INIT_CACHE; + } + + // Used for position(). + private int getCachedChar(int index) throws SQLException + { + int realIndex = index - cacheOffset_; + if (realIndex >= cache_.length) + { + int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE; + int len = (int)length(); + if (len < 0) len = 0x7FFFFFFF; + if ((blockSize+index) > len) blockSize = len-index; + cache_ = getSubString(index+1, blockSize).toCharArray(); + cacheOffset_ = index; + realIndex = 0; + } + if (cache_.length == 0) return -1; + return cache_[realIndex]; + } + + + + /** + Returns the position at which a pattern is found in the CLOB. + This method is not supported. + + @param pattern The pattern. + @param position The position within the CLOB to begin + searching (1-based). +@return The position in the CLOB at which the pattern was found, + or -1 if the pattern was not found. + + @exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. + **/ + public long position(String pattern, long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= length()) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + char[] charPattern = pattern.toCharArray(); + int end = (int)length() - charPattern.length; + + // We use a cache of chars so we don't have to read in the entire + // contents of the CLOB. + initCache(); + + for (int i=offset; i<=end; ++i) + { + int j = 0; + int cachedChar = getCachedChar(i+j); + while (j < charPattern.length && cachedChar != -1 && charPattern[j] == cachedChar) + { + ++j; + cachedChar = getCachedChar(i+j); + } + if (j == charPattern.length) return i+1; + } + return -1; + } + } + + + + /** + Returns the position at which a pattern is found in the CLOB. + This method is not supported. + + @param pattern The pattern. + @param position The position within the CLOB to begin + searching (1-based). +@return The position in the CLOB at which the pattern was found, + or -1 if the pattern was not found. + + @exception SQLException If the pattern is null, + the position is not valid, + or an error occurs. + **/ + public long position(Clob pattern, long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + if (pattern == null || offset < 0 || offset >= length()) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + int patternLength = (int)pattern.length(); + int locatorLength = (int)length(); + if (patternLength > locatorLength || patternLength < 0) return -1; + + int end = locatorLength - patternLength; + + char[] charPattern = pattern.getSubString(1L, patternLength).toCharArray(); //@CRS - Get all chars for now, improve this later. + + // We use a cache of chars so we don't have to read in the entire + // contents of the CLOB. + initCache(); + + for (int i=offset; i<=end; ++i) + { + int j = 0; + int cachedChar = getCachedChar(i+j); + while (j < patternLength && cachedChar != -1 && charPattern[j] == cachedChar) + { + ++j; + cachedChar = getCachedChar(i+j); + } + if (j == patternLength) return i+1; + } + + return -1; + } + } + + + /** + Returns a stream that an application can use to write Ascii characters to this CLOB. + The stream begins at position position, and the CLOB will be truncated + after the last character of the write. + + @param position The position (1-based) in the CLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + **/ + public OutputStream setAsciiStream(long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + try + { + return new AS400JDBCClobLocatorOutputStream(this, position, ConvTable.getTable(819, null)); + } + catch (UnsupportedEncodingException e) + { + // Should never happen. + JDError.throwSQLException(JDError.EXC_INTERNAL, e); + return null; + } + } + + + + /** + Returns a stream that an application can use to write a stream of Unicode characters to + this CLOB. The stream begins at position position, and the CLOB will + be truncated after the last character of the write. + + @param position The position (1-based) in the CLOB where writes should start. + @return An OutputStream object to which data can be written by an application. + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + + **/ + public Writer setCharacterStream(long position) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + if (position <= 0 || position > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + return new AS400JDBCWriter(this, position); + } + + + + /** + Writes a String to this CLOB, starting at position position. The CLOB + will be truncated after the last character written. + + @param position The position (1-based) in the CLOB where writes should start. + @param stringToWrite The string that will be written to the CLOB. + @return The number of characters that were written. + + @exception SQLException If there is an error accessing the CLOB or if the position + specified is greater than the length of the CLOB. + + **/ + public int setString(long position, String stringToWrite) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int offset = (int)position-1; + + if (offset < 0 || offset >= maxLength_ || stringToWrite == null) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many chars as we can. If our internal char array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of chars that were set. + char[] charsToWrite = stringToWrite.toCharArray(); + int newSize = offset + charsToWrite.length; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + int numChars = newSize - offset; + if (numChars != charsToWrite.length) + { + char[] temp = charsToWrite; + charsToWrite = new char[newSize]; + System.arraycopy(temp, 0, charsToWrite, 0, numChars); + } + + // We don't really know if all of these chars can be written until we go to + // the system, so we just return the char[] length as the number written. + byte[] bytesToWrite = converter_.stringToByteArray(charsToWrite, 0, charsToWrite.length); + locator_.writeData((long)offset, bytesToWrite, false); //@K1A + return charsToWrite.length; + } + } + + + + /** + Writes a String to this CLOB, starting at position position in the CLOB. + The CLOB will be truncated after the last character written. The lengthOfWrite + characters written will start from offset in the string that was provided by the + application. + + @param position The position (1-based) in the CLOB where writes should start. + @param string The string that will be written to the CLOB. + @param offset The offset into string to start reading characters (0-based). + @param lengthOfWrite The number of characters to write. + @return The number of characters written. + + @exception SQLException If there is an error accessing the CLOB value or if the position + specified is greater than the length of the CLOB. + + **/ + public int setString(long position, String string, int offset, int lengthOfWrite) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int clobOffset = (int)position-1; + if (clobOffset < 0 || clobOffset >= maxLength_ || + string == null || offset < 0 || lengthOfWrite < 0 || (offset+lengthOfWrite) > string.length() || + (clobOffset+lengthOfWrite) > maxLength_) + { + throw JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + // We will write as many chars as we can. If our internal char array + // would overflow past the 2 GB boundary, we don't throw an error, we just + // return the number of chars that were set. + int newSize = clobOffset + lengthOfWrite; + if (newSize < 0) newSize = 0x7FFFFFFF; // In case the addition resulted in overflow. + int numChars = newSize - clobOffset; + int realLength = (numChars < lengthOfWrite ? numChars : lengthOfWrite); + char[] charsToWrite = new char[realLength]; + string.getChars(offset, offset + numChars, charsToWrite, 0); //@K2C + + // We don't really know if all of these chars can be written until we go to + // the system, so we just return the char[] length as the number written. + byte[] bytesToWrite = converter_.stringToByteArray(charsToWrite, 0, charsToWrite.length); + locator_.writeData((long)clobOffset, bytesToWrite, false); //@k1A + return charsToWrite.length; + } + } + + + + /** + Truncates this CLOB to a length of lengthOfCLOB characters. + + @param lengthOfCLOB The length, in characters, that this CLOB should be after + truncation. + + @exception SQLException If there is an error accessing the CLOB or if the length + specified is greater than the length of the CLOB. + + **/ + public void truncate(long lengthOfCLOB) throws SQLException + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) + { + int length = (int)lengthOfCLOB; + if (length < 0 || length > maxLength_) + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + //truncate_ = length; + + // The host server does not currently provide a way for us + // to truncate the temp space used to hold the locator data, + // so we just keep track of it ourselves. This should work, + // since the temp space on the system should only be valid + // within the scope of our transaction/connection. That means + // there's no reason to go to the system to update the data, + // since no other process can get at it. + locator_.writeData(length, new byte[0], 0, 0, true); //@k1A + } + } + + //@PDA 550 + /** + * This method frees the Clob object and releases the + * resources that it holds. The object is invalid once the + * free method is called. If free is called + * multiple times, the subsequent calls to free are treated + * as a no-op. + * + * @throws SQLException + * if an error occurs releasing the Clob's resources + */ + public void free() throws SQLException //@sync + { + if(locator_ == null) + return; //no-op + + synchronized(locator_) //@sync + { + locator_.free(); + + locator_ = null; //@pda make objects available for GC + converter_ = null; + savedObject_ = null; + cache_ = null; + } + } + + // @PDA jdbc40 + /** + * Returns a Reader object that contains a partial + * Clob value, starting with the character specified by pos, + * which is length characters in length. + * + * @param pos + * the offset to the first character of the partial value to be + * retrieved. The first character in the Clob is at position 1. + * @param length + * the length in characters of the partial value to be retrieved. + * @return Reader through which the partial Clob + * value can be read. + * @throws SQLException + * if pos is less than 1 or if pos is greater than the number of + * characters in the Clob or if pos + length is + * greater than the number of characters in the + * Clob + */ + public Reader getCharacterStream(long pos, long length) throws SQLException //@sync + { + if(locator_ == null)//@free + JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); //@free + + synchronized(locator_) //@sync + { + if (pos < 1 || (pos - 1 + length) > locator_.getMaxLength() || length < 0 ) //@pdc change parm check like getSubString + { + JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + Reader r = null; + + try + { + //@xml3 if xml column, remove xml declaration via ConvTableReader + r = new ConvTableReader(new AS400JDBCInputStream( locator_), converter_.getCcsid(), converter_.bidiStringType_, isXML_); //@xml3 + r.skip(pos); + return r; + } + catch (UnsupportedEncodingException e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + catch (IOException e) + { + JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); + return null; + } + } + } + + /** Get the locator handle corresponding to this ClobLocator + * + */ + public int getLocator() { + return locator_.getHandle(); + } +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCConnection.java b/jdbc40/com/ibm/as400/access/AS400JDBCConnection.java new file mode 100644 index 000000000..c569ac9f2 --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCConnection.java @@ -0,0 +1,5703 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCConnection.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.SocketException; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +/* ifdef JDBC40 */ +import java.sql.ClientInfoStatus; +import java.sql.SQLClientInfoException; +import java.sql.SQLPermission; +/* endif */ +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +/* ifdef JDBC40 */ +import java.sql.NClob; +/* endif */ +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +/* ifdef JDBC40 */ +import java.sql.SQLXML; +/* endif */ +import java.sql.Statement; +import java.sql.Savepoint; // @E10a +import java.sql.Struct; +import java.util.Enumeration; // @DAA +/* ifdef JDBC40 */ +import java.util.HashMap; +/* endif */ +import java.util.Map; +import java.util.Properties; +import java.util.Vector; +/* ifdef JDBC40 */ +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.Executor; +/* endif */ + + +/** +

The AS400JDBCConnection class provides a JDBC connection +to a specific DB2 for IBM i database. Use +DriverManager.getConnection() to create new AS400JDBCConnection +objects. + +

There are many optional properties that can be specified +when the connection is created. Properties can be specified either +as part of the URL or in a java.util.Properties object. See +JDBC properties for a complete +list of properties supported by the AS400JDBCDriver. + +

Note that a connection may contain at most 9999 open +statements. +**/ +// +// Implementation notes: +// +// 1. Each connection and statement has an "id" associated with +// it. All ids are unique within a connection, and this +// uniqueness is maintained by the id table for each +// connection. +// +// The id is used as a convention for assigning each +// connection and statement its own ORS (Operation Result +// Set) on the IBM i as well as assigning each statement +// its own RPB (Request Parameter Block). +// +// Every communication to the database requires a connection +// and an id within that connection. +// +// 2. It is a requirement that no finalize() methods need to +// receive a reply from the IBM i system. Because of the way the +// AS400Server class is implemented, certain scenarios where +// this is the case will result in deadlock. The AS400Server +// class provides sendAndDiscardReply() specifically to avoid +// this problem. +// +// Within the JDBC driver, finalize() usually calls one or more +// close() methods. Therefore, this requirement is also +// imposed on close() methods. +// +// 3. All requests for the connection and the related objects in +// its context should be sent via a variation of one of the +// sendXXX() methods. This makes debugging cleaner. +// +public class AS400JDBCConnection +/* ifdef JDBC40 */ +extends ToolboxWrapper +/* endif */ +implements Connection +{ + + private class CancelLock extends Object {} //@C7A + private class HeldRequestsLock extends Object {} //@C7A + + // Turn this flag on to prevent this Connection object from establishing an actual connection to the IBM i system. This is useful when doing multi-threaded stress testing on the Toolbox's built-in JDBC connection pool manager, where we create/delete massive numbers of connections. + // For production, this flag _must_ be set to 'false'. + private static final boolean TESTING_THREAD_SAFETY = false; //@CPMa + + // This is a compile time flag for doing simple + // communications traces. + // + // The choices are: + // 0 = No communication trace (for production code). + // 1 = Only request and reply ids. + // 2 = Request and reply ids and contents. + // + // Note that the LL (length) and parameter count for + // requests will not be accurate, since they have not yet + // been set at the time when the request is dumped. + // + private static int DEBUG_COMM_TRACE_ = 0; + + + + // This is a compile time flag for temporarily disabling + // request chaining. This can be useful when a request + // is failing, but all we see is an error class == 7, + // return code == -1000. This means a chain request + // failed. + // + // The choices are: + // true = Enable request chaining (for production code). + // false = Disable request chaining. + // + // @E5D private static final boolean DEBUG_REQUEST_CHAINING_ = true; + + + + // This is a compile time flag for forcing the use of + // extended datastream formats. This can be useful when + // testing extended formats, but the IBM i system is not reporting + // the correct VRM. + // + // The choices are: + // true = Force extended datastream formats. + // false = Decide based on system VRM (for production code). + // + // @E9D private static final boolean FORCE_EXTENDED_FORMATS_ = false; + + // @F8 -- the key change is to put a 1 in the 7th position. That 1 is the "ODBC" flag. + // The IBM i passes it along to database to enable correct package caching of + // "where current of" statements. This flag affects only package caching. + private static final String CLIENT_FUNCTIONAL_LEVEL_= "V7R1M01 "; // @EDA F8c H2c pdc 610 + + private static final int DRDA_SCROLLABLE_CUTOFF_ = 129; // @B1A + private static final int DRDA_SCROLLABLE_MAX_ = 255; // @DAA + private static final int INITIAL_STATEMENT_TABLE_SIZE_ = 256; // @DAA + static final int UNICODE_CCSID_ = 13488; // @E3C + + // The max number of open statements per connection. If this @DAA + // changes, then change the relevant sentence in the javadoc, too. @DAA + static final int MAX_STATEMENTS_ = 9999; // @DAC + private final boolean[] assigned_ = new boolean[MAX_STATEMENTS_]; //@P0C + + static final int DATA_COMPRESSION_NONE_ = 0; // @ECA + static final int DATA_COMPRESSION_OLD_ = 1; // @ECA + static final int DATA_COMPRESSION_RLE_ = 0x3832; // @ECA @EIC @EJC + + + // Private data. + private AS400ImplRemote as400_; + private AS400 as400PublicClassObj_; // Prevents garbage collection. + //@P0D private BitSet assigned_; // @DAC + private boolean cancelling_; // @E8A + private CancelLock cancelLock_ = new CancelLock(); // @E8A@C7C + private String catalog_; + boolean checkStatementHoldability_ = false; // @F3A //@XAC + private boolean closing_; // @D4A + private boolean aborted_ = false; // @D7A + ConvTable converter_; //@P0C + private int dataCompression_ = -1; // @ECA + private JDDataSourceURL dataSourceUrl_; + private boolean drda_; // @B1A + private String defaultSchema_; + private boolean extendedFormats_; + // @E2D private ConverterImplRemote graphicConverter_; + // @E2D private boolean graphicConverterLoaded_; + private Vector heldRequests_; // @E5A + private HeldRequestsLock heldRequestsLock_ = new HeldRequestsLock(); // @E5A@C7C + private int holdability_ = AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED; // @G4A + private int id_; + private AS400JDBCDatabaseMetaData metaData_; + private JDPackageManager packageManager_; + private JDProperties properties_; + private boolean readOnly_; + //@P0D private BitSet requestPending_; // @DAC + //@P1Dprivate final boolean[] requestPending_ = new boolean[MAX_STATEMENTS_]; //@P0A + private AS400Server server_; + private int serverFunctionalLevel_; // @E7A + private String serverJobIdentifier_ = null; // @E8A + private SQLWarning sqlWarning_; + private Vector statements_; // @DAC + JDTransactionManager transactionManager_; // @E10c + static final ConvTable unicodeConverter_ = new ConvTable13488(); // @E3A @P0C + ConvTable packageCCSID_Converter = null; //Bidi-HCG + int vrm_; // @D0A @E10c + private int correlationID_ = 0; //@D2A - only used for multiple receives + // declare the user-supplied value for server trace. The constants for + // the definition of each bit in the bit map are defined in Trace.java + private int traceServer_ = 0; // @j1a + + // set to true if database host server tracing is started via the setDBHostServerTrace method + private boolean databaseHostServerTrace_ = false; // @2KR + + private boolean mustSpecifyForUpdate_ = true; // @j31 + + //counter to keep track of number of open statements + private int statementCount_ = 0; //@K1A + private boolean thousandStatements_ = false; //@K1A + + private String qaqqiniLibrary_ = null; //@K2A + + //@KBA Specifies level of autocommit support to use. + // If V5R2 or earlier use old support of running SET TRANSACTION STATEMENTS (0) + // If "true autocommit" connection property is false - run autocommit under *NONE isolation (1) + // If "true autocommit" connection property is true - run with specified isolation (2) + int newAutoCommitSupport_ = 1; //@KBA + + private boolean wrappedInsert_ = false; // @GKA + //@pda 550 client info + //Names for clientInfo identifiers. DatabaseMetadata also will use these names + static final String applicationNamePropertyName_ = "ApplicationName"; + static final String clientUserPropertyName_ = "ClientUser"; + static final String clientHostnamePropertyName_ = "ClientHostname"; + static final String clientAccountingPropertyName_ = "ClientAccounting"; + static final String clientProgramIDPropertyName_ = "ClientProgramID"; //@pda + + //@pda 550 client info values + private String applicationName_ = ""; //@pdc so can be added to Properties object in getClientInfo() + private String clientUser_ = ""; //@pdc + private String clientHostname_ = ""; //@pdc + private String clientAccounting_ = ""; //@pdc + private String clientProgramID_ = ""; //@pdc + + private int concurrentAccessResolution_ = AS400JDBCDataSource.CONCURRENTACCESS_NOT_SET; //@cc1 + + private boolean doUpdateDeleteBlocking_ = false; //@A2A + private int maximumBlockedInputRows_ = 32000; //@A6A + + protected final static int QUERY_TIMEOUT_QQRYTIMLMT = 0; + protected final static int QUERY_TIMEOUT_CANCEL = 1; + + private int queryTimeoutMechanism_ = QUERY_TIMEOUT_QQRYTIMLMT; + + // @K3 determine variable field compression settings + boolean variableFieldCompressionPropertyEvaluated_ = false; + boolean useVariableFieldCompression_ = false; + boolean useVariableFieldInsertCompression_ = false; + + /** + Static initializer. Initializes the reply data streams + that we expect to receive. + **/ + static + { + // The database server will only return 1 type of reply. + //@P0D AS400Server.addReplyStream (new DBReplyRequestedDS (), + AS400Server.addReplyStream(DBDSPool.getDBReplyRequestedDS(), //@P0A + AS400.DATABASE); + } + + + + // The default constructor reserved for use within the package. + AS400JDBCConnection () //@A3A + { + } + + + + // @A3D Deleted constructor: + // AS400JDBCConnection (JDDataSourceURL dataSourceUrl, JDProperties properties) + // throws SQLException + + + + // @E8A + /** + Cancels a statement within this connection. + + @param id The ID of the statement. + + @exception SQLException If the statement cannot be executed. + **/ + void cancel(int id) + throws SQLException + { + // Lock out all other operations for this connection. + synchronized(cancelLock_) + { + if (TESTING_THREAD_SAFETY) return; // in certain testing modes, don't contact the system + cancelling_ = true; + AS400JDBCConnection cancelConnection = null; + try + { + // If the server job identifier was returned, and the system is at a + // functional level 5 or greater, then use the job identifier to issue + // the cancel from another connection. Otherwise, do nothing. + if ((serverJobIdentifier_ != null) && (serverFunctionalLevel_ >= 5)) + { + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Cancelling statement " + id); + + // Create another connection to issue the cancel. + cancelConnection = new AS400JDBCConnection(); + + //AS400 system = new AS400(as400PublicClassObj_); + //cancelConnection.setSystem(system); + + cancelConnection.setProperties(dataSourceUrl_, properties_, as400_, true); + + // Send the cancel request. + DBSQLRequestDS request = null; + DBReplyRequestedDS cancelReply = null; + try + { + request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_CANCEL, id_, + DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0); + request.setJobIdentifier(serverJobIdentifier_, converter_); + cancelReply = cancelConnection.sendAndReceive (request); + + int errorClass = cancelReply.getErrorClass(); + int returnCode = cancelReply.getReturnCode(); + if (errorClass != 0) + JDError.throwSQLException(this, id_, errorClass, returnCode); + } + catch (DBDataStreamException e) + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + finally + { + if (request != null) { + request.returnToPool(); request = null; + } + if (cancelReply != null) { + cancelReply.returnToPool(); cancelReply = null; + } + } + } + else + { + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Cancel of statement " + id + " requested, but is not supported by system"); + } + } + finally + { + // always need to close the connection + if (cancelConnection != null) { + try { cancelConnection.close(); } + catch (Throwable e) {} // ignore any exceptions + } + + // Let others back in. + cancelling_ = false; + cancelLock_.notifyAll(); + } + } + } + + + + /** + Checks that the specified SQL statement can be executed. + This decision is based on the access specified by the caller + and the read only mode. + + @param sqlStatement The SQL statement. + + @exception SQLException If the statement cannot be executed. + **/ + void checkAccess (JDSQLStatement sqlStatement) + throws SQLException + { + String access = properties_.getString (JDProperties.ACCESS); + + // If we only have read only access, then anything other + // than a SELECT can not be executed. + if ((access.equalsIgnoreCase (JDProperties.ACCESS_READ_ONLY)) + && (! sqlStatement.isSelect ())) { + // Do not throw exception if we have a metadata call @K5A + if (! sqlStatement.getIsMetaDataCall()) { + JDError.throwSQLException (this, JDError.EXC_ACCESS_MISMATCH); + } + } + + // If we have read call access, then anything other than + // a SELECT or CALL can not be executed. + if (((readOnly_) + || ((access.equalsIgnoreCase (JDProperties.ACCESS_READ_CALL)))) + && (! sqlStatement.isSelect()) + && (! sqlStatement.isProcedureCall())) + JDError.throwSQLException (this, JDError.EXC_ACCESS_MISMATCH); + } + + + + // @E8A + /** + Checks to see if we are cancelling a statement. If so, wait until the + cancel is done. If not, go ahead. + **/ + private void checkCancel() + { + synchronized(cancelLock_) + { + while (cancelling_) + { + try + { + cancelLock_.wait(); + } + catch (InterruptedException e) + { + // Ignore. + } + } + } + } + + + //@F3A + /** + Checks if what the user passed in for holdability is valid. + **/ + private boolean checkHoldabilityConstants (int holdability) + { + if ((holdability == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) || + (holdability == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT) || + (holdability == AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED)) + { + return true; + } + return false; + } + + + /** + Checks that the connection is open. Public methods + that require an open connection should call this first. + + @exception SQLException If the connection is not open. + **/ + void checkOpen () + throws SQLException + { + if (TESTING_THREAD_SAFETY) return; // in certain testing modes, don't contact IBM i system + if (aborted_ || (server_ == null)) + JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE); + } + + + + /** + Clears all warnings that have been reported for the connection. + After this call, getWarnings() returns null until a new warning + is reported for the connection. + + @exception SQLException If an error occurs. + **/ + public void clearWarnings () + throws SQLException + { + sqlWarning_ = null; + } + + + + /** + Releases the connection's resources immediately instead of waiting + for them to be automatically released. This rolls back any active + transactions, closes all statements that are running in the context + of the connection, and disconnects from the IBM i system. + + @exception SQLException If an error occurs. + **/ + // + // Implementation notes: + // + // 1. We do not have to worry about thread synchronization here, + // since the AS400Server object handles it. + // + // 2. It is a requirement to not get replies during a finalize() + // method. Since finalize() calls this method, this requirement + // applies here, too. + // + public void close () + throws SQLException + { + // @D4A + // Avoid recursion. When we close associated statements, they try + // to close this connection. + if (closing_) return; + closing_ = true; + + // If this is already closed, then just do nothing. + // + // The spec does not define what happens when a connection + // is closed multiple times. The official word from the Sun + // JDBC team is that "the driver's behavior in this case + // is implementation defined. Applications that do this are + // non-portable." + if (isClosed ()) + return; + + // partial close (moved rollback and closing of all the statements). @E1 + pseudoClose(); + + // Disconnect from the system. + if (server_ != null) + { + + // @B3 It turns out that we were closing the connection, + // @B3 then the AS400Server object was in its disconnectServer() + // @B3 method. Since the AS400Server object needs to do other + // @B3 cleanup, we still need to call it. + + // @B3D try { + // @B3D DBSQLEndCommDS request = new DBSQLEndCommDS ( + // @B3D DBSQLEndCommDS.FUNCTIONID_END_COMMUNICATION, + // @B3D id_, 0, 0); + // @B3D send (request); + // @B3D } + // @B3D catch (Exception e) { + // @B3D JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + // @B3D } + + + + + as400_.disconnectServer (server_); + server_ = null; + } + + if (JDTrace.isTraceOn()) + JDTrace.logClose (this); + } + + /* + * handle the processing of the abort. @D7A + */ +void handleAbort() { + + // Cancel any existing statement. + try { + cancel(0); + } catch (SQLException e ) { + // Ingore any errors + } + closing_ = true; + // partial close (moved rollback and closing of all the statements). + try { + pseudoClose(); + } catch (SQLException e) { + // Just ignore and continue + } + + // Disconnect from the system. + if (server_ != null) + { + as400_.disconnectServer (server_); + server_ = null; + } +} + + // @E4C + /** + Commits all changes made since the previous commit or + rollback and releases any database locks currently held by + the connection. This has no effect when the connection + is in auto-commit mode. + +

This method can not be called when the connection is part + of a distributed transaction. See + AS400JDBCXAResource for more information. + + @exception SQLException If the connection is not open + or an error occurs. + **/ + public void commit () + throws SQLException + { + checkOpen (); + + if (!transactionManager_.isLocalTransaction()) // @E4A + JDError.throwSQLException (this, JDError.EXC_TXN_STATE_INVALID); // @E4A + + // Note: CPS 72CSHT support + if (transactionManager_.getAutoCommit () && properties_.getBoolean(JDProperties.AUTOCOMMIT_EXCEPTION)) //@CE1 + JDError.throwSQLException (this, JDError.EXC_FUNCTION_SEQUENCE); //@CE1 + + // Note: Intuitively, it seems like if we are in + // auto-commit mode, that we should not need to + // do anything for an explicit commit. However, + // somewhere along the line, the system gets + // confused, so we go ahead an send the commit + // anyway. + + transactionManager_.commit (); + + // @F3 If cursor hold property is false, then mark the cursors closed. Don't worry here + // @F3 about whether their statement level holdability is different; we will check that + // @F3 within AS400JDBCStatement.markCursorsClosed(). + // @F3 If the user has changed any statement's holdability, then we need to go through + // @F3 the enumeration to see if there are ones where we may need to close our cursors + // @F3 or internal result sets. + // @F3 Passing true to markCursorsClosed means we called this method from rollback(). + if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_FALSE // @B4A + || (checkStatementHoldability_ && getVRM() >= JDUtilities.vrm520)) // @F3A + markCursorsClosed(false); // @B4A + + if(!getAutoCommit() && properties_.getBoolean(JDProperties.HOLD_STATEMENTS )) //@KBL if auto commit is off, check to see if any statements have been partially closed //@PDA additional HOLD_STATEMENTS check + markStatementsClosed(); //@KBL + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Transaction commit"); + } + + + //@F3A + /** + Sets a flag for whether the user has changed the holdability for any of the statements that + came from this connection. As of JDBC 3.0, the user can specify a statement-level holdability + that is different from the statement-level holdability. Rather than always going through all + of the statements to see if any of their holidabilities is different, we will mark this flag if + the user changes any of the statement holdabilities. + + @exception SQLException If the connection is not open + or an error occurs. + **/ + void setCheckStatementHoldability(boolean check) + { + checkStatementHoldability_ = check; + } + + + + /** + Corrects the result set type based on the result set concurrency + and posts a warning. + + @param resultSetType The result set type. + @param resultSetConcurrency The result set concurrency. + @return The correct result set type. + **/ + private int correctResultSetType (int resultSetType, + int resultSetConcurrency) + throws SQLException // @EGA + { + int newResultSetType = (resultSetConcurrency == ResultSet.CONCUR_UPDATABLE) + ? ResultSet.TYPE_SCROLL_SENSITIVE : ResultSet.TYPE_SCROLL_INSENSITIVE; + postWarning (JDError.getSQLWarning (JDError.WARN_OPTION_VALUE_CHANGED)); + return newResultSetType; + } + + + + /** + Creates a Statement object for executing SQL statements without + parameters. If the same SQL statement is executed many times, it + is more efficient to use prepareStatement(). + +

Result sets created using the statement will be type + ResultSet.TYPE_FORWARD_ONLY and concurrency + ResultSet.CONCUR_READ_ONLY. + + @return The statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, or an + error occurs. + **/ + public Statement createStatement () + throws SQLException + { + return createStatement (ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY, getInternalHoldability()); //@G4C + } + + + + // JDBC 2.0 + /** + Creates a Statement object for executing SQL statements without + parameters. If the same SQL statement is executed many times, it + is more efficient to use prepareStatement(). + + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @return The statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type or currency is not supported, + or an error occurs. + **/ + public Statement createStatement (int resultSetType, + int resultSetConcurrency) + throws SQLException + { + return createStatement (resultSetType, //@G4A + resultSetConcurrency, getInternalHoldability()); //@G4A + //@G4M Moved code to createStatement (int, int, int) + } + + + //@G4A JDBC 3.0 + /** + Creates a Statement object for executing SQL statements without + parameters. If the same SQL statement is executed many times, it + is more efficient to use prepareStatement(). + +

Full functionality of this method requires support in OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, the value for + resultSetHoldability will be ignored. + + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @param resultSetHoldability The result set holdability. Valid values are: + + @return The statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not supported, + or an error occurs. + @since Modification 5 + **/ + public Statement createStatement (int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + // Validation. + checkOpen (); + if (! metaData_.supportsResultSetConcurrency (resultSetType, resultSetConcurrency)) + resultSetType = correctResultSetType (resultSetType, resultSetConcurrency); + + if (!checkHoldabilityConstants (resultSetHoldability)) //@F3A + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); //@F3A + + // Create the statement. + int statementId = getUnusedId (resultSetType); // @B1C + AS400JDBCStatement statement = new AS400JDBCStatement (this, + statementId, transactionManager_, packageManager_, + properties_.getString (JDProperties.BLOCK_CRITERIA), + properties_.getInt (JDProperties.BLOCK_SIZE), + properties_.getBoolean (JDProperties.PREFETCH), + properties_.getString (JDProperties.PACKAGE_CRITERIA), // @A2A + resultSetType, resultSetConcurrency, resultSetHoldability, //@G4A + AS400JDBCStatement.GENERATED_KEYS_NOT_SPECIFIED); //@G4A + statements_.addElement(statement); // @DAC + statementCount_++; //@K1A + if(thousandStatements_ == false && statementCount_ == 1000) //@K1A + { //@K1A + thousandStatements_ = true; //@K1A + //post warning //@K1A + postWarning(JDError.getSQLWarning(JDError.WARN_1000_OPEN_STATEMENTS)); //@K1A + } //@K1A + + if (JDTrace.isTraceOn()) //@F4A + { //@F4A + int size = statements_.size(); //@F4A + if (size % 256 == 0) //@F4A + { //@F4A + JDTrace.logInformation (this, "Warning: Open handle count now: " + size); //@F4A + } //@F4A + } //@F4A + + return statement; + } + + + + + /** + Outputs debug information for a request. This should only be used + for debugging the JDBC driver and is not intended for production code. + + @param request The request. + **/ + private void debug (DBBaseRequestDS request) + { + if (DEBUG_COMM_TRACE_ >= 1) + System.out.println ("Server request: " + + Integer.toString (request.getServerID(), 16).toUpperCase() + + ":" + Integer.toString (request.getReqRepID(), 16).toUpperCase() + + "."); + if (DEBUG_COMM_TRACE_ >= 2) + request.dump (System.out); + } + + + + /** + Outputs debug information for a reply. This should only be used + for debugging the JDBC driver and is not intended for production code. + + @param reply The reply. + **/ + private void debug (DBReplyRequestedDS reply) + { + if (DEBUG_COMM_TRACE_ >= 1) + System.out.println ("Server reply: " + + Integer.toString (reply.getServerID(), 16).toUpperCase() + + ":" + Integer.toString (reply.getReturnDataFunctionId(), 16).toUpperCase() + + "."); + if (DEBUG_COMM_TRACE_ >= 2) + reply.dump (System.out); + + + if (DEBUG_COMM_TRACE_ >= 1) + { + int returnCode = ((DBReplyRequestedDS) reply).getReturnCode(); + int errorClass = ((DBReplyRequestedDS) reply).getErrorClass(); + if ((errorClass != 0) || (returnCode != 0)) + System.out.println ("Server error = " + errorClass + ":" + + returnCode + "."); + } + } + + + + /** + Closes the connection if not explicitly closed by the caller. + + @exception Throwable If an error occurs. + **/ + protected void finalize () + throws Throwable + { + if (! isClosed ()) { + JDTrace.logInformation (this, "WARNING: Finalizer thread closing connection object."); + close (); + } + super.finalize (); + } + + + + /** + Returns the AS400 object for this connection. + + @return The AS400 object. + **/ + AS400Impl getAS400 () + throws SQLException // @EGA + { + return as400_; + } + + + + /** + Returns the auto-commit state. + + @return true if the connection is in auto-commit mode; + false otherwise. + + @exception SQLException If the connection is not open. + **/ + public boolean getAutoCommit () + throws SQLException + { + checkOpen (); + return transactionManager_.getAutoCommit (); + } + + + + /** + Returns the catalog name. + + @return The catalog name. + + @exception SQLException If the connection is not open. + **/ + public String getCatalog () + throws SQLException + { + checkOpen (); + return catalog_; + } + + //@cc1 + /** + * This method returns the concurrent access resolution setting. + * This method has no effect on IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @return The concurrent access resolution setting. Possible return valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public int getConcurrentAccessResolution () + { + return concurrentAccessResolution_; + } + + /** + Returns the converter for this connection. + + @return The converter. + **/ + //@P0D ConverterImplRemote getConverter () + //@P0D throws SQLException // @EGA + //@P0D { + //@P0D return converter_; + //@P0D } + + + + /** + Returns the converter for the specified CCSID, unless + it is 0 or 65535 (i.e. probably set for a non-text field), in + which case it returns the converter for this connection. + This is useful for code that handles all types of fields + in a generic manner. + + @param ccsid The CCSID. + @return The converter. + + @exception SQLException If the CCSID is not valid. + **/ + ConvTable getConverter (int ccsid) //@P0C + throws SQLException + { + try + { + if (ccsid == 0 || ccsid == 1 || ccsid == 65535 || ccsid == -1) return converter_; //@P0C + //@P0D switch (ccsid) + //@P0D { // @E3A + //@P0D case 65535: //@ELC // @E3A + //@P0D case 0: // @E3A + //@P0D case 1: // @E3A + //@P0D return converter_; // @E3A + //@P0D case UNICODE_CCSID_: // @E3A + //@P0D if (unicodeConverter_ == null) // @E3A + //@P0D unicodeConverter_ = ConverterImplRemote.getConverter(13488, as400_); // @E3A + //@P0D return unicodeConverter_; // @E3A + //@P0D default: // @E3A + //@P0D return ConverterImplRemote.getConverter (ccsid, as400_); // @E3C + //@P0D } // @E3A + return ConvTable.getTable(ccsid, null); //@P0A + } + catch (UnsupportedEncodingException e) + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + return null; + } + } + + + // @ECA + /** + Returns the style of data compression. + + @return The style of data compression. Possible values are DATA_COMPRESSION_NONE_, + DATA_COMPRESSION_OLD_, and DATA_COMPRESSION_RLE_. + **/ + int getDataCompression() // @ECA + { // @ECA + return dataCompression_; // @ECA + } // @ECA + + + + /** + Returns the default SQL schema. + + @return The default SQL schema, or QGPL if none was + specified. + **/ + String getDefaultSchema () + throws SQLException // @EGA + { + return((defaultSchema_ == null) ? "QGPL" : defaultSchema_); + } + + + //@DELIMa + /** + Returns the default SQL schema. + + @param returnRawValue Indicates what to return if default SQL schema has not been set. If true, return raw value; if false, then return QGPL rather than null. + @return The default SQL schema. If returnRawValue==false and no default SQL schema was specified, then return QGPL rather than null. + **/ + String getDefaultSchema (boolean returnRawValue) + throws SQLException + { + return((returnRawValue || defaultSchema_ != null) ? defaultSchema_ : "QGPL"); + } + + + //@G4A JDBC 3.0 + /** + Returns the holdability of ResultSets created from this connection. + + @return The cursor holdability. Valid values are ResultSet.HOLD_CURSORS_OVER_COMMIT and + ResultSet.CLOSE_CURSORS_AT_COMMIT. The holdability is derived in this order + of precedence: + + Full functionality of #1 requires support in OS/400 + V5R2 or IBM i. If connecting to OS/400 V5R1 or earlier, + the value specified on this method will be ignored and the default holdability + will be the value of #2. + + @exception SQLException If the connection is not open. + @since Modification 5 + **/ + public int getHoldability () + throws SQLException + { + checkOpen (); + // If holdability has been set, return its value. + if ((holdability_ == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) || + (holdability_ == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT)) + { + return holdability_; + } + // Else, holdability either equals AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED + // or has an incorrect value (shouldn't be able to happen). + // Return the holdability determined by seeing what the cursor hold driver property + // was set to. Default is HOLD_CURSORS_AT_COMMIT. + else + { + if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_TRUE) + return AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT; + else if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_FALSE) + return AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT; + // Hold indicator will be set to -1 if the user gave us a bad number in setHoldIndicator(). + // We threw an exception there, so throw another exception here, then return default + // value for driver. + else + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL); + return AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT; + } + } + } + + + //@DELIMa + /** + Returns the ID of the connection. + @return The connection ID. + **/ + int getID() + { + return id_; + } + + + //@G4A JDBC 3.0 + /** + Returns the holdability of ResultSets created from this connection. + Use this method internally to return the value specified if the user has called + setHoldability(int), or HOLDABILITY_NOT_SPECIFIED if that + method hasn't been called, meaning to use the old behavior and not the new code + point for cursor holdability. + + @return The cursor holdability. Valid values are + AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT, + AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT, + and AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED. + + @since Modification 5 + **/ + int getInternalHoldability () + { + return holdability_; + } + + + + // @E2D /** + // @E2D Returns the graphic converter for this connection. + // @E2D + // @E2D @return The graphic converter. + // @E2D + // @E2D @exception SQLException If no graphic converter was loaded. + // @E2D **/ + // @E2D // + // @E2D // Implementation note: + // @E2D // + // @E2D // * Graphic data is pure double-byte, so we will need a + // @E2D // different converter for that. If there is no associated + // @E2D // double-byte CCSID, or the converter can not be loaded, + // @E2D // then we should throw an exception. We wait to load this, + // @E2D // since the majority of callers do not need this converter. + // @E2D // + // @E2D ConverterImplRemote getGraphicConverter () + // @E2D throws SQLException + // @E2D { + // @E2D // If the graphic converter has not yet been loaded, + // @E2D // then do so. + // @E2D if (graphicConverterLoaded_ == false) { + // @E2D int serverGraphicCCSID = ExecutionEnvironment.getAssociatedDbcsCcsid (converter_.getCcsid ()); + // @E2D if (serverGraphicCCSID != -1) { + // @E2D try { + // @E2D graphicConverter_ = ConverterImplRemote.getConverter (serverGraphicCCSID, as400_); + // @E2D } + // @E2D catch (UnsupportedEncodingException e) { + // @E2D graphicConverter_ = null; + // @E2D } + // @E2D } + // @E2D + // @E2D if (JDTrace.isTraceOn ()) { + // @E2D if (graphicConverter_ != null) + // @E2D JDTrace.logInformation (this, "Server graphic CCSID = " + serverGraphicCCSID); + // @E2D else + // @E2D JDTrace.logInformation (this, "No graphic CCSID was loaded"); + // @E2D } + // @E2D } + // @E2D + // @E2D // Return the graphic converter, or throw an exception. + // @E2D if (graphicConverter_ == null) + // @E2D JDError.throwSQLException (this, JDError.EXC_CCSID_INVALID); + // @E2D return graphicConverter_; + // @E2D } + + + + /** + Returns the DatabaseMetaData object that describes the + connection's tables, supported SQL grammar, stored procedures, + capabilities and more. + + @return The metadata object. + + @exception SQLException If an error occurs. + **/ + public DatabaseMetaData getMetaData () + throws SQLException + { + // We allow a user to get this object even if the + // connection is closed. + + return metaData_; + } + + + + /** + Returns the connection properties. + + @return The connection properties. + **/ + JDProperties getProperties () + throws SQLException // @EGA + { + return properties_; + } + + + + // @E8A + /** + Returns the job identifier of the host server job corresponding to this connection. + Every JDBC connection is associated with a host server job on the IBM i system. The + format is: + + +

Note: Since this method is not defined in the JDBC Connection interface, + you typically need to cast a Connection object to AS400JDBCConnection in order + to call this method: +

+    String serverJobIdentifier = ((AS400JDBCConnection)connection).getServerJobIdentifier();
+    
+ + @return The server job identifier, or null if not known. + **/ + public String getServerJobIdentifier() // @E8A + { // @E8A + return serverJobIdentifier_; // @E8A + } // @E8A + + + + + int getServerFunctionalLevel() // @EEA + { // @EEA + return serverFunctionalLevel_; // @EEA + } // @EEA + + + // @EHA + /** + Returns the system object which is managing the connection to the system. + +

Note: Since this method is not defined in the JDBC Connection interface, + you typically need to cast a Connection object to AS400JDBCConnection in order + to call this method: +

+    AS400 system = ((AS400JDBCConnection)connection).getSystem();
+    
+ + @return The system. + **/ + // Implementation note: Don't use this object internally because we could be running in a proxy environment + // The purpose of this method is to simply hold the full AS400 object so it can be retrieved from the Connection + public AS400 getSystem() // @EHA + { // @EHA + return as400PublicClassObj_; // @EHA + } // @EHA + + + + + + /** + Returns the transaction isolation level. + + @return The transaction isolation level. Possible + values are: + + + @exception SQLException If the connection is not open. + **/ + public int getTransactionIsolation () + throws SQLException + { + checkOpen (); + return transactionManager_.getIsolation (); + } + + + + JDTransactionManager getTransactionManager() // @E4A + { // @E4A + return transactionManager_; // @E4A + } // @E4A + + + + // JDBC 2.0 + /** + Returns the type map. + +

This driver does not support the type map. + + @return The type map. + + @exception SQLException This exception is always thrown. + **/ + public Map getTypeMap () + throws SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + + + // @B1C + /** + Returns the next unused id. + + @param resultSetType The result set type. This is + relevant only when the connection + is being used for DRDA. + @return The next unused id. + **/ + // + // Implementation note: This method needs to be synchronized + // so that the same id does not get assigned twice. + // + private int getUnusedId (int resultSetType) //@P0C + throws SQLException + { + synchronized(assigned_) //@P1A + { + // Note: We will always assume id 0 is being used, + // since that represents the connection itself. + + // If this connection is being used for DRDA, then we + // must use statement ids of 1-128 for non-scrollable + // cursors and 129-255 for scrollable cursors. + if (drda_) + { + if (resultSetType == ResultSet.TYPE_FORWARD_ONLY) + { + for (int i = 1; i < DRDA_SCROLLABLE_CUTOFF_; ++i) + { + //@P0Dif (assigned_.get(i) == false) + //@P0D{ // @DAC + //@P0D assigned_.set(i); // @DAC + //@P0D return i; + //@P0D} + if (!assigned_[i]) //@P0A + { + assigned_[i] = true; //@P0A + return i; //@P0A + } + } + } + else + { + for (int i = DRDA_SCROLLABLE_CUTOFF_; i < DRDA_SCROLLABLE_MAX_; ++i) + { // @DAC + //@P0Dif (assigned_.get(i) == false) + //@P0D{ // @DAC + //@P0D assigned_.set(i); // @DAC + //@P0D return i; + //@P0D} + if (!assigned_[i]) //@P0A + { + assigned_[i] = true; //@P0A + return i; //@P0A + } + } + } + } + + // If this connection is NOT being used for DRDA, then + // we can use any statement id. + else + { + for (int i = 1; i < MAX_STATEMENTS_; ++i) + { + //@P0Dif (assigned_.get(i) == false) + //@P0D{ // @DAC + //@P0D assigned_.set(i); // @DAC + //@P0D return i; + //@P0D} + if (!assigned_[i]) //@P0A + { + assigned_[i] = true; //@P0A + return i; //@P0A + } + } + } + + // All ids are being used. + JDError.throwSQLException (this, JDError.EXC_MAX_STATEMENTS_EXCEEDED); + return -1; + } + } + + + + // @j31a new method -- Must the user have "for update" on their + // SQL statement to guarantee an updatable cursor? The answer is + // no for v5r2 and v5r1 systems with a PTF. For V5R1 systems + // without the PTF, v4r5, and earlier, the answer is yes. + boolean getMustSpecifyForUpdate () + { + return mustSpecifyForUpdate_; + } + + + + + + /** + Returns the URL for the connection's database. + + @return The URL for the database. + **/ + String getURL () + throws SQLException // @EGA + { + return dataSourceUrl_.toString (); + } + + + + /** + Returns the user name as currently signed on to the system. + + @return The user name. + **/ + String getUserName () + throws SQLException // @EGA + { + if (TESTING_THREAD_SAFETY) // in certain testing modes, don't contact IBM i system + { + String userName = as400_.getUserId (); + if (userName == null || userName.length() == 0) { + userName = as400PublicClassObj_.getUserId(); + } + return userName; + } + + return as400_.getUserId (); + } + + + + int getVRM() // @D0A + throws SQLException // @EGA + { // @D0A + return vrm_; // @D0A + } // @D0A + + + + /** + Returns the first warning reported for the connection. + Subsequent warnings may be chained to this warning. + + @return The first warning or null if no warnings + have been reported. + + @exception SQLException If an error occurs. + **/ + public SQLWarning getWarnings () + throws SQLException + { + return sqlWarning_; + } + + + + /** + Indicates if the specified cursor name is already used + in the connection. + + @return true if the cursor name is already used; + false otherwise. + **/ + boolean isCursorNameUsed (String cursorName) + throws SQLException // @EGA + { + // Make a clone of the vector, since it will be modified as each statement @FAA + Vector statements = (Vector)statements_.clone(); + + Enumeration list = statements.elements(); // @DAA + while (list.hasMoreElements()) + { // @DAC + try { + if (((AS400JDBCStatement)list.nextElement()).getCursorName().equalsIgnoreCase(cursorName)) // @DAC + return true; + } catch (Exception e) { /*@FAA */ + // ignore any exceptions + if (JDTrace.isTraceOn()) { + JDTrace.logException(this, "isCursorNameUsed caught exception", e); + } + + } + } + return false; + } + + + + /** + Indicates if the connection is closed. + + @return true if the connection is closed; false + otherwise. + + @exception SQLException If an error occurs. + **/ + public boolean isClosed () + throws SQLException + { + if (aborted_) return true; /*@D7A*/ + + if (TESTING_THREAD_SAFETY) return false; // in certain testing modes, don't contact IBM i system + + if (server_ == null) // @EFC + return true; // @EFA + if (!server_.isConnected()) + { // @EFA + server_ = null; // @EFA + return true; // @EFA + } // @EFA + else // @EFA + return false; // @EFA + } + + + + /** + Indicates if the connection is in read-only mode. + + @return true if the connection is in read-only mode; + false otherwise. + + @exception SQLException If the connection is not open. + **/ + public boolean isReadOnly () + throws SQLException + { + checkOpen (); + return((readOnly_) || isReadOnlyAccordingToProperties()); // @CPMc + } + + // Called by AS400JDBCPooledConnection. + boolean isReadOnlyAccordingToProperties() + throws SQLException + { + checkOpen (); + return((properties_.getString (JDProperties.ACCESS).equalsIgnoreCase (JDProperties.ACCESS_READ_ONLY)) + || (properties_.getString (JDProperties.ACCESS).equalsIgnoreCase (JDProperties.ACCESS_READ_CALL))); + } + + + // @B4A + /** + Marks all of the cursors as closed. + + @param isRollback True if we called this from rollback(), false if we called this from commit(). + **/ + void markCursorsClosed(boolean isRollback) //@F3C //@XAC + throws SQLException //@F2A + { + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Testing to see if cursors should be held."); //@F3C + // Make a clone of the vector, since it will be modified as each statement + // closes itself. @FAA + Vector statements = (Vector)statements_.clone(); + Enumeration list = statements.elements(); // @DAA + while (list.hasMoreElements()) // @DAC + { //@KBL + AS400JDBCStatement statement = (AS400JDBCStatement)list.nextElement(); //@KBL + //@KBLD ((AS400JDBCStatement)list.nextElement()).markCursorClosed(isRollback); // @DAC @F3C + // If the statement is held open, all of the result sets have already been closed + + // If we happen to get an exception, just ignore it. There exists a + // race condition where another thread could have closed the connected while + // we were looping through the statement elements. @F7A + try { + if(!statement.isHoldStatement()) //@KBL + statement.markCursorClosed(isRollback); //@KBL + } catch (SQLException ex) { + if (JDTrace.isTraceOn()) { + JDTrace.logException(this, "markCursorsClosed caught exception", ex); + } + } + } //@KBL + } + + //@KBL + /* + If a statement associated with locators has been partially closed, finish closing the statement object. + A statement may become partially closed if the user closed the statement and set the "hold statements" connection + property to true when making the connection. Additionally, the statement must have been used to access a locator. + */ + private void markStatementsClosed() + { + if(!statements_.isEmpty()) + { + // Make a clone of the vector, since it will be modified as each statement + // closes itself. + // @KBL Close any statements the user called close on that were associated with locators. + Vector statements = (Vector)statements_.clone(); + Enumeration list = statements.elements(); + while (list.hasMoreElements()) + { + AS400JDBCStatement statement = (AS400JDBCStatement)list.nextElement(); + try + { + if(statement.isHoldStatement()) + { + statement.setAssociatedWithLocators(false); + statement.finishClosing(); + } + } + catch (SQLException e) + { + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Closing statement after rollback failed: " + e.getMessage()); + } + } + } + } + + //@GKA + // Note: This method is used when the user supplies either the column indexes or names + // to the execute/executeUpdate/prepareStatement method. + /* + * Prepares and executes the statement needed to retrieve generated keys. + */ + String makeGeneratedKeySelectStatement(String sql, int[] columnIndexes, String[] columnNames) + throws SQLException + { + if(columnIndexes != null) + { + //verify there is a column index in the specified array + if(columnIndexes.length == 0) + JDError.throwSQLException(JDError.EXC_ATTRIBUTE_VALUE_INVALID); + + //Prepare a statement in order to retrieve the column names associated with the indexes specified in the array + //wrapper the statement with a select * from final table + // @B4C. Use NEW TABLE instead of FINAL TABLE. With FINAL TABLE, the query will fail if + // AFTER INSERT TRIGGERS are present. Since it is unlikely that AFTER INSERT triggers will + // change the autogenerated keys, NEW TABLE is used. + StringBuffer selectAll = new StringBuffer("SELECT * FROM NEW TABLE("); + selectAll.append(sql); + selectAll.append(")"); + PreparedStatement genPrepStat = prepareStatement(selectAll.toString()); + + // retrieve the JDServerRow object associated with this statement. It contains the column name info. + JDServerRow results = ((AS400JDBCPreparedStatement)genPrepStat).getResultRow(); + columnNames = new String[columnIndexes.length]; + try{ + for(int j=0; jResult sets created using the statement will be type + ResultSet.TYPE_FORWARD_ONLY and concurrency + ResultSet.CONCUR_READ_ONLY. + + @param sql The SQL stored procedure call. + @return The callable statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, or an + error occurs. + **/ + public CallableStatement prepareCall (String sql) + throws SQLException + { + return prepareCall (sql, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY, getInternalHoldability()); //@G4A + } + + + + // JDBC 2.0 + /** + Precompiles an SQL stored procedure call with optional input + and output parameters and stores it in a CallableStatement + object. This object can be used to efficiently call the SQL + stored procedure multiple times. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type or currency is not valid, + or an error occurs. + **/ + public CallableStatement prepareCall (String sql, + int resultSetType, + int resultSetConcurrency) + throws SQLException + { + return prepareCall(sql, resultSetType, resultSetConcurrency, + getInternalHoldability()); //@G4A + //@G4M Moved code below + } + + + //@G4A JDBC 3.0 + /** + Precompiles an SQL stored procedure call with optional input + and output parameters and stores it in a CallableStatement + object. This object can be used to efficiently call the SQL + stored procedure multiple times. + +

Full functionality of this method requires support in OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, the value for + resultSetHoldability will be ignored. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @return The prepared statement object. + @param resultSetHoldability The result set holdability. Valid values are: + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not valid, + or an error occurs. + @since Modification 5 + **/ + public CallableStatement prepareCall (String sql, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + // Validation. + checkOpen (); + if (! metaData_.supportsResultSetConcurrency (resultSetType, resultSetConcurrency)) + resultSetType = correctResultSetType (resultSetType, resultSetConcurrency); + + if (!checkHoldabilityConstants(resultSetHoldability)) //@F3A + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); //@F3A + + // Create the statement. + JDSQLStatement sqlStatement = new JDSQLStatement (sql, + properties_.getString (JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString (JDProperties.PACKAGE_CRITERIA), this); // @A2A @G4A + int statementId = getUnusedId (resultSetType); // @B1C + AS400JDBCCallableStatement statement = new AS400JDBCCallableStatement (this, + statementId, transactionManager_, packageManager_, + properties_.getString (JDProperties.BLOCK_CRITERIA), + properties_.getInt (JDProperties.BLOCK_SIZE), + sqlStatement, + properties_.getString (JDProperties.PACKAGE_CRITERIA), + resultSetType, resultSetConcurrency, resultSetHoldability, //@G4A + AS400JDBCStatement.GENERATED_KEYS_NOT_SPECIFIED); //@G4A + statements_.addElement(statement); // @DAC + statementCount_++; //@K1A + if(thousandStatements_ == false && statementCount_ == 1000) //@K1A + { //@K1A + thousandStatements_ = true; //@K1A + //post warning //@K1A + postWarning(JDError.getSQLWarning(JDError.WARN_1000_OPEN_STATEMENTS)); //@K1A + } //@K1A + + if (JDTrace.isTraceOn()) //@F4A + { //@F4A + int size = statements_.size(); //@F4A + if (size % 256 == 0) //@F4A + { //@F4A + JDTrace.logInformation (this, "Warning: Open handle count now: " + size); //@F4A + } //@F4A + } //@F4A + + return statement; + } + + + + + /** + Precompiles an SQL statement with optional input parameters + and stores it in a PreparedStatement object. This object can + be used to efficiently execute this SQL statement + multiple times. + +

Result sets created using the statement will be type + ResultSet.TYPE_FORWARD_ONLY and concurrency + ResultSet.CONCUR_READ_ONLY. + + @param sql The SQL statement. + @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, or an + error occurs. + **/ + public PreparedStatement prepareStatement (String sql) + throws SQLException + { + return prepareStatement (sql, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY, + getInternalHoldability()); //@G4A + } + + + + //@G4A + //JDBC 3.0 + /** + Precompiles an SQL statement with optional input parameters + and stores it in a PreparedStatement object. This object can + be used to efficiently execute this SQL statement + multiple times. + +

This method requires OS/400 V5R2 or IBM i. If connecting to OS/400 V5R1 or earlier, an exception will be + thrown. + +

Result sets created using the statement will be type + ResultSet.TYPE_FORWARD_ONLY and concurrency + ResultSet.CONCUR_READ_ONLY. + + @param sql The SQL statement. + @param autoGeneratedKeys Whether to return auto generated keys. Valid values are: +

+ @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, + if connecting to OS/400 V5R1 or earlier, + an error occurs. + @since Modification 5 + **/ + public PreparedStatement prepareStatement (String sql, int autoGeneratedKeys) + throws SQLException + { + if (getVRM() < JDUtilities.vrm520) //@F5A + JDError.throwSQLException(this, JDError.EXC_FUNCTION_NOT_SUPPORTED); //@F5A + + // Validation. + checkOpen (); + + // Create the statement. + JDSQLStatement sqlStatement = new JDSQLStatement (sql, + properties_.getString (JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString (JDProperties.PACKAGE_CRITERIA), this); // @A2A @G4A + + if(getVRM() >= JDUtilities.vrm610 && autoGeneratedKeys==Statement.RETURN_GENERATED_KEYS) //@GKA added new generated key support + { + // check if it is an insert statement. + // Note: this should be false if the statement was wrappered with a SELECT + // when prepareStatement(String sql, int[] columnIndex) or + // prepareStatement(String sql, String[] columnNames) was called. + if(sqlStatement.isInsert_) + { + //wrapper the statement + String selectStatement = makeGeneratedKeySelectStatement(sql); + sqlStatement = new JDSQLStatement (selectStatement, properties_.getString(JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString(JDProperties.PACKAGE_CRITERIA), this); + wrappedInsert_ = true; + + } + } + int statementId = getUnusedId (ResultSet.TYPE_FORWARD_ONLY); // @B1C + + if(wrappedInsert_) + { + sqlStatement.setSelectFromInsert(true); + wrappedInsert_ = false; + } + + AS400JDBCPreparedStatement statement = new AS400JDBCPreparedStatement (this, + statementId, transactionManager_, packageManager_, + properties_.getString (JDProperties.BLOCK_CRITERIA), + properties_.getInt (JDProperties.BLOCK_SIZE), + properties_.getBoolean (JDProperties.PREFETCH), + sqlStatement, false, + properties_.getString (JDProperties.PACKAGE_CRITERIA), + ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, + getInternalHoldability(), autoGeneratedKeys); //@G4A + statements_.addElement(statement); // @DAC + statementCount_++; //@K1A + if(thousandStatements_ == false && statementCount_ == 1000) //@K1A + { //@K1A + thousandStatements_ = true; //@K1A + //post warning //@K1A + postWarning(JDError.getSQLWarning(JDError.WARN_1000_OPEN_STATEMENTS)); //@K1A + } //@K1A + + if (JDTrace.isTraceOn()) //@F4A + { //@F4A + int size = statements_.size(); //@F4A + if (size % 256 == 0) //@F4A + { //@F4A + JDTrace.logInformation (this, "Warning: Open handle count now: " + size); //@F4A + } //@F4A + } //@F4A + + return statement; + } + + + + + // JDBC 2.0 + /** + Precompiles an SQL statement with optional input parameters + and stores it in a PreparedStatement object. This object can + be used to efficiently execute this SQL statement + multiple times. + +

Result sets created using the statement will be holdability + ResultSet.CLOSE_CURSORS_AT_COMMIT. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type or currency is not valid, + or an error occurs. + **/ + public PreparedStatement prepareStatement (String sql, + int resultSetType, + int resultSetConcurrency) + throws SQLException + { + return prepareStatement (sql, resultSetType, //@G4A + resultSetConcurrency, getInternalHoldability()); //@G4A + //@G4M Moved code to next method. + } + + + //@G4A + // JDBC 3.0 + /** + Precompiles an SQL statement with optional input parameters + and stores it in a PreparedStatement object. This object can + be used to efficiently execute this SQL statement + multiple times. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: + + @param resultSetConcurrency The result set concurrency. Valid values are: + + @param resultSetHoldability The result set holdability. Valid values are: + + @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not valid, + or an error occurs. + **/ + public PreparedStatement prepareStatement (String sql, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + // Validation. + checkOpen (); + if (! metaData_.supportsResultSetConcurrency (resultSetType, resultSetConcurrency)) + resultSetType = correctResultSetType (resultSetType, resultSetConcurrency); + + if (!checkHoldabilityConstants(resultSetHoldability)) //@F3A + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); //@F3A + + // Create the statement. + JDSQLStatement sqlStatement = new JDSQLStatement (sql, + properties_.getString (JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString (JDProperties.PACKAGE_CRITERIA), this); // @A2A @G4A + int statementId = getUnusedId (resultSetType); // @B1C + AS400JDBCPreparedStatement statement = new AS400JDBCPreparedStatement (this, + statementId, transactionManager_, packageManager_, + properties_.getString (JDProperties.BLOCK_CRITERIA), + properties_.getInt (JDProperties.BLOCK_SIZE), + properties_.getBoolean (JDProperties.PREFETCH), + sqlStatement, false, + properties_.getString (JDProperties.PACKAGE_CRITERIA), + resultSetType, resultSetConcurrency, resultSetHoldability, //@G4A + AS400JDBCStatement.GENERATED_KEYS_NOT_SPECIFIED); //@G4A + statements_.addElement(statement); // @DAC + statementCount_++; //@K1A + if(thousandStatements_ == false && statementCount_ == 1000) //@K1A + { //@K1A + thousandStatements_ = true; //@K1A + //post warning //@K1A + postWarning(JDError.getSQLWarning(JDError.WARN_1000_OPEN_STATEMENTS)); //@K1A + } //@K1A + + if (JDTrace.isTraceOn()) //@F4A + { //@F4A + int size = statements_.size(); //@F4A + if (size % 256 == 0) //@F4A + { //@F4A + JDTrace.logInformation (this, "Warning: Open handle count now: " + size); //@F4A + } //@F4A + } //@F4A + + return statement; + } + + // @G4 new method + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement + * multiple times. + * + *

This method is not supported when connecting to IBM i V5R4 or earlier systems. + * + * @param sql The SQL statement. + * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row or rows. + * @return The prepared statement object. + * @exception java.sql.SQLException - If connecting to IBM i V5R4 or earlier systems, + * the connection is not open, + * the maximum number of statements for this connection has been reached, + * or an error occurs. + * @since Modification 5 + **/ + public PreparedStatement prepareStatement (String sql, int[] columnIndexes) + throws SQLException + { + if(getVRM() >= JDUtilities.vrm610) //@GKA added support for generated keys + { + // Validation + checkOpen(); + + //Create a JDSQLStatement + JDSQLStatement sqlStatement = new JDSQLStatement (sql, + properties_.getString (JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString (JDProperties.PACKAGE_CRITERIA), this); + //Check if the statement is an insert + if(sqlStatement.isInsert_){ + wrappedInsert_ = true; + return prepareStatement(makeGeneratedKeySelectStatement(sql, columnIndexes, null), Statement.RETURN_GENERATED_KEYS); + } + else // treat like prepareStatement(sql) was called + return prepareStatement(sql); + } + else //@GKA Throw an exception. V5R4 and earlier does not support retrieving generated keys by column index. + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + } + + + // @G4 new method + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement + * multiple times. + * + *

This method is not supported when connecting to IBM i V5R4 or earlier systems. + * + * @param sql The SQL statement. + * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or rows. + * @return The prepared statement object. + * @exception java.sql.SQLException - If connecting to IBM i V5R4 or earlier systems, + * the connection is not open, + * the maximum number of statements for this connection has been reached, + * or an error occurs. + * @since Modification 5 + **/ + public PreparedStatement prepareStatement (String sql, String[] columnNames) + throws SQLException + { + if(getVRM() >= JDUtilities.vrm610) //@GKA added generated key support + { + //Validation + checkOpen(); + + //Create a JDSQLStatement + JDSQLStatement sqlStatement = new JDSQLStatement (sql, + properties_.getString (JDProperties.DECIMAL_SEPARATOR), true, + properties_.getString (JDProperties.PACKAGE_CRITERIA), this); + //Check if the statement is an insert + if(sqlStatement.isInsert_){ + wrappedInsert_ = true; + return prepareStatement(makeGeneratedKeySelectStatement(sql, null, columnNames), Statement.RETURN_GENERATED_KEYS); + } + else // treat like prepareStatement(sql) was called + return prepareStatement(sql); + } + else //@GKA Throw an exception. V5R4 and earlier does not support retrieving generated keys by column name. + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + } + + + + //@E10a new method + void processSavepointRequest(String savepointStatement) + throws SQLException + { + // must be OS/400 v5r2 or IBM i + if (vrm_ < JDUtilities.vrm520) + JDError.throwSQLException(this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + + // cannot do savepoints on XA transactions + if (!transactionManager_.isLocalTransaction()) + JDError.throwSQLException (this, JDError.EXC_TXN_STATE_INVALID); + + // cannot do savepoints if autocommit on + if (getAutoCommit()) + JDError.throwSQLException(this, JDError.EXC_TXN_STATE_INVALID); + + Statement statement = null; //@scan1 + try{ + statement = createStatement(); + + statement.executeUpdate(savepointStatement); + + }finally //@scan1 + { + if(statement != null) //@scan1 + statement.close(); + + } + } + + + + + + + + /** + Partial closing of the connection. + @exception SQLException If a database error occurs. + **/ + void pseudoClose() throws SQLException // @E1 + { + // Rollback before closing. + if ((transactionManager_.isLocalTransaction()) && (transactionManager_.isLocalActive())) // @E4A + rollback (); + + // Close all statements that are running in the context of this connection. + // Make a clone of the vector, since it will be modified as each statement @DAA + // closes itself. // @DAA + // @j4 change -- close may throw a SQLException. Log that error and keep going. + // Since the user called close we won't return until we tried to close all + // statements. + Vector statements = (Vector)statements_.clone(); // @DAA + Enumeration list = statements.elements(); // @DAA + while (list.hasMoreElements()) // @DAC + { + // @DAC + AS400JDBCStatement statement = (AS400JDBCStatement)list.nextElement(); // @DAA + try + { // @J4a + if(statement.isHoldStatement()) //@KBL user already called close, now completely close it + { //@KBL + statement.setAssociatedWithLocators(false); //@KBL + statement.finishClosing(); //@KBL + } //@KBL + // @J4a + if (! statement.isClosed()) // @DAC + statement.close(); // @DAC + } // @J4a + catch (SQLException e) // @J4a + { + // @J4a + if (JDTrace.isTraceOn()) // @J4a + JDTrace.logInformation (this, "Closing statement while closing connection failed: " + e.getMessage()); // @j4a + } // @J4a + } + + // @j1a clean up any IBM i debug that is going on. This entire block + // is new for @J1 + if (traceServer_ > 0 || databaseHostServerTrace_) // @2KRC + { + // Get the job identifier because we need the id (it is part of some + // of our trace files). I know I could have saved it from + // the start-trace code but tracing is not performance critical so + // why make the object bigger by storing trace stuff as member data. + String serverJobIdentifier = getServerJobIdentifier(); + + // Same for this flag. Don't want to grow the object by saving + // this as member data. + boolean preV5R1 = true; + boolean SQLNaming = properties_.getString(JDProperties.NAMING).equals(JDProperties.NAMING_SQL); + + try + { + preV5R1 = getVRM() <= JDUtilities.vrm450; + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed, could not get server VRM"); + } + + boolean endedTraceJob = false; //@540 Used to determine if ENDTRC has already been done. + // End trace-job + if ((traceServer_ & ServerTrace.JDBC_TRACE_SERVER_JOB) > 0) + { + try + { + if (preV5R1) + JDUtilities.runCommand(this, "QSYS/TRCJOB SET(*OFF) OUTPUT(*PRINT)", SQLNaming); + else + { + JDUtilities.runCommand(this, "QSYS/ENDTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") DTAOPT(*LIB) DTALIB(QUSRSYS) RPLDTA(*YES) PRTTRC(*YES)", SQLNaming ); + + JDUtilities.runCommand(this, "QSYS/DLTTRC DTAMBR(QJT" + + serverJobIdentifier.substring(20) + + ") DTALIB(QUSRSYS)", SQLNaming ); + } + endedTraceJob = true; //@540 + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed"); + } + } + + //@540 End database host server trace job + // Database Host Server Trace is supported on V5R3+ + if(getVRM() >= JDUtilities.vrm530 && !endedTraceJob) + { + // Only issue ENDTRC if not already done. + if(((traceServer_ & ServerTrace.JDBC_TRACE_DATABASE_HOST_SERVER) > 0) || databaseHostServerTrace_) // @2KRC + { + // end database host server trace + try{ + JDUtilities.runCommand(this, "QSYS/ENDTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") DTAOPT(*LIB) DTALIB(QUSRSYS) RPLDTA(*YES) PRTTRC(*YES)", SQLNaming ); + + JDUtilities.runCommand(this, "QSYS/DLTTRC DTAMBR(QJT" + + serverJobIdentifier.substring(20) + + ") DTALIB(QUSRSYS)", SQLNaming ); + } + catch(Exception e){ + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end database host server tracing failed."); + } + } + } + + // End debug-job + if ((traceServer_ & ServerTrace.JDBC_DEBUG_SERVER_JOB) > 0) + { + try + { + JDUtilities.runCommand(this, "QSYS/ENDDBG", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed, could not end debug on server job "); + } + } + + // End the database monitor + if ((traceServer_ & ServerTrace.JDBC_START_DATABASE_MONITOR) > 0) + { + try + { + JDUtilities.runCommand(this, "QSYS/ENDDBMON", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed, could not end database monitor"); + } + } + + // Dump out SQL information + if (((traceServer_ & ServerTrace.JDBC_SAVE_SQL_INFORMATION) > 0) && !preV5R1) + { + try + { + JDUtilities.runCommand(this, "QSYS/PRTSQLINF *JOB", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed, could not print SQL information"); + } + } + + // Dump the joblog + if ((traceServer_ & ServerTrace.JDBC_SAVE_SERVER_JOBLOG) > 0) + { + try + { + JDUtilities.runCommand(this, "QSYS/DSPJOBLOG JOB(*) OUTPUT(*PRINT)", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end server job tracing failed, could not save job log"); + } + } + + // If the user set our flag to turn on client tracing then turn it back off. + // This may turn off tracing even though the user wanted it on for some other + // reason but there is no way for this code to know why tracing was turned on. + // It does know this interface is one reason it is on so we will assume it + // is the only reason and will turn it off here. + if ((traceServer_ & ServerTrace.JDBC_TRACE_CLIENT) > 0) + JDTrace.setTraceOn(false); + } + } + + + // @E10a new method + /** + * Removes the given Savepoint object from the current transaction. + * Any reference to the savepoint after it has been removed will + * cause an SQLException to be thrown. + * + * @param savepoint the savepoint to be removed. + * + * @exception SQLException if a database access error occurs or the given Savepoint + * is not a valid savepoint in the current transaction. + * + * @since Modification 5 + **/ + public void releaseSavepoint(Savepoint savepoint) + throws SQLException + { + if (savepoint == null) + throw new NullPointerException("savepoint"); + + AS400JDBCSavepoint sp = (AS400JDBCSavepoint) savepoint; + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Releasing savepoint " + sp.getName()); + + if (sp.getStatus() != AS400JDBCSavepoint.ACTIVE) + JDError.throwSQLException(this, JDError.EXC_SAVEPOINT_DOES_NOT_EXIST); + + String SQLCommand = "RELEASE SAVEPOINT " + sp.getName(); + + processSavepointRequest(SQLCommand); + + sp.setStatus(AS400JDBCSavepoint.CLOSED); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Savepoint " + sp.getName() + " released."); + } + + + + + + + + // @E4C + /** + Drops all changes made since the previous commit or + rollback and releases any database locks currently held by + the connection. This has no effect when the connection + is in auto-commit mode. + +

This method can not be called when the connection is part + of a distributed transaction. See + AS400JDBCXAResource for more information. + + @exception SQLException If the connection is not open + or an error occurs. + **/ + public void rollback () + throws SQLException + { + checkOpen (); + + if (!transactionManager_.isLocalTransaction()) // @E4A + JDError.throwSQLException (this, JDError.EXC_TXN_STATE_INVALID); // @E4A + + if (transactionManager_.getAutoCommit () && properties_.getBoolean(JDProperties.AUTOCOMMIT_EXCEPTION)) + JDError.throwSQLException (this, JDError.EXC_FUNCTION_SEQUENCE); + + if (! transactionManager_.getAutoCommit ()) + { + transactionManager_.rollback (); + + // @F3 Mark all cursors closed on a rollback. Don't worry here + // @F3 about whether their statement level holdability is different; we will check + // @F3 that within Statement.markCursorsClosed(). + + // @F3D if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_FALSE // @B4A + // @F3 Passing true means we called markCursorClosed from rollback. + markCursorsClosed(true); // @B4A @F3C + + if(properties_.getBoolean(JDProperties.HOLD_STATEMENTS )) //@PDA additional HOLD_STATEMENTS check + markStatementsClosed(); //@KBL + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Transaction rollback"); + } + } + + // @E10 new method + /** + * Undoes all changes made after the specified Savepoint was set. + * + * @param savepoint the savepoint to be rolled back to. + * + * @exception SQLException if a database access error occurs, the Savepoint + * is no longer valid, or this Connection + * is currently in auto-commit mode. + * @since Modification 5 + **/ + public void rollback(Savepoint savepoint) + throws SQLException + { + if (savepoint == null) + throw new NullPointerException("savepoint"); + + + AS400JDBCSavepoint sp = (AS400JDBCSavepoint) savepoint; + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Rollback with savepoint " + sp.getName()); + + if (sp.getStatus() != AS400JDBCSavepoint.ACTIVE) + JDError.throwSQLException(this, JDError.EXC_SAVEPOINT_DOES_NOT_EXIST); + + String SQLCommand = "ROLLBACK TO SAVEPOINT " + sp.getName(); + + processSavepointRequest(SQLCommand); + + sp.setStatus(AS400JDBCSavepoint.CLOSED); + + if(properties_.getBoolean(JDProperties.HOLD_STATEMENTS )) //@PDA additional HOLD_STATEMENTS check + markStatementsClosed(); //@KBL + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Rollback with savepoint " + sp.getName() + " complete."); + } + + + + + + + /** + Sends a request data stream to the system using the + connection's id and does not expect a reply. + + @param request The request. + + @exception SQLException If an error occurs. + **/ + // + // See implementation notes for sendAndReceive(). + // + void send (DBBaseRequestDS request) + throws SQLException + { + send (request, id_, true); + } + + + + /** + Sends a request data stream to the system and does not + expect a reply. + + @param request The request. + @param id The id. + + @exception SQLException If an error occurs. + **/ + // + // See implementation notes for sendAndReceive(). + // + void send (DBBaseRequestDS request, int id) + throws SQLException + { + send (request, id, true); + } + + + + /** + Sends a request data stream to the system and does not + expect a reply. + + @param request The request. + @param id The id. + @param leavePending Indicates if the request should + be left pending. This indicates + whether or not to base the next + request on this one. + + @exception SQLException If an error occurs. + **/ + // + // See implementation notes for sendAndReceive(). + // + void send (DBBaseRequestDS request, int id, boolean leavePending) + throws SQLException + { + checkCancel(); // @E8A + checkOpen(); // @W1a + + try + { + // Since we are just calling send() (instead of sendAndReceive()), // @EAA + // make sure we are not asking the system for a reply. Otherwise, // @EAA + // the reply will come back and it will get held in the AS400 // @EAA + // read daemon indefinitely - - a memory leak. // @EAA + if (JDTrace.isTraceOn()) + { // @EAA + if (request.getOperationResultBitmap() != 0) // @EAA + JDTrace.logInformation (this, "Reply requested but not collected:" + request.getReqRepID()); // @EAA + } // @EAA + + request.setBasedOnORSHandle (0); // @DAC @EKC + // DBReplyRequestedDS reply = null; + + if (dataCompression_ == DATA_COMPRESSION_RLE_) + { // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REQUEST_RLE_COMPRESSION); // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REPLY_RLE_COMPRESSION); // @ECA + request.compress(); // @ECA + } // @ECA + + DataStream actualRequest; // @E5A + synchronized(heldRequestsLock_) + { // @E5A + if (heldRequests_ != null) // @E5A + actualRequest = new DBConcatenatedRequestDS(heldRequests_, request); // @E5A + else // @E5A + actualRequest = request; // @E5A + heldRequests_ = null; // @E5A + + server_.send(actualRequest); // @E5A @F7M +//@P1D requestPending_[id] = leavePending; //@P0A @F7M + } // @E5A + + // @E5D if (DEBUG_REQUEST_CHAINING_ == true) { + //@P0D if (leavePending) // @DAA + //@P0D requestPending_.set(id); // @DAC + //@P0D else // @DAA + //@P0D requestPending_.clear(id); // @DAA + + // @E5D } + // @E5D else { + // @E5D request.addOperationResultBitmap (DBBaseRequestDS.ORS_BITMAP_RETURN_DATA); + // @E5D reply = (DBReplyRequestedDS) server_.sendAndReceive (request); + // @E5D requestPending_[id] = false; + // @E5D } + + if (DEBUG_COMM_TRACE_ > 0) + { + debug (request); + // @E5D if (DEBUG_REQUEST_CHAINING_ == false) + // @E5D debug (reply); + } + } + // @J5D catch (ConnectionDroppedException e) { // @C1A + // @J5D server_ = null; // @D8 + // @J5D request.freeCommunicationsBuffer(); // @EMa + // @J5D JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE, e); // @C1A + // @J5D } // @C1A + catch (IOException e) + { // @J5A + server_ = null; // @J5A + //@P0D request.freeCommunicationsBuffer(); // @J5A + JDError.throwSQLException (this, JDError.EXC_COMMUNICATION_LINK_FAILURE, e); // @J5A + } // @J5A + catch (Exception e) + { + //@P0D request.freeCommunicationsBuffer(); // @EMa + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + } + + + + // @EBD /** + // @EBD Sends a request data stream to the system and discards + // @EBD the reply. + // @EBD + // @EBD @param request The request. + // @EBD @param id The id. + // @EBD @param leavePending Indicates if the request should + // @EBD be left pending. This indicates + // @EBD whether or not to base the next + // @EBD request on this one. + // @EBD + // @EBD @exception SQLException If an error occurs. + // @EBD **/ + // @EBD // + // @EBD // See implementation notes for sendAndReceive(). + // @EBD // + // @EBD void sendAndDiscardReply (DBBaseRequestDS request, int id) + // @EBD throws SQLException + // @EBD { + // @EBD checkCancel(); // @E8A + // @EBD + // @EBD try { + // @EBD request.setBasedOnORSHandle (0); //@EKC + // @EBD + // @EBD DataStream actualRequest; // @E5A + // @EBD synchronized(heldRequestsLock_) { // @E5A + // @EBD if (heldRequests_ != null) // @E5A + // @EBD actualRequest = new DBConcatenatedRequestDS(heldRequests_, request); // @E5A + // @EBD else // @E5A + // @EBD actualRequest = request; // @E5A + // @EBD heldRequests_ = null; // @E5A + // @EBD } // @E5A + // @EBD + // @EBD server_.sendAndDiscardReply(actualRequest); // @E5C + // @EBD requestPending_[id] = false; + // @EBD + // @EBD if (DEBUG_COMM_TRACE_ > 0) + // @EBD debug (request); + // @EBD } + // @EBD catch (ConnectionDroppedException e) { // @C1A + // @EBD server_ = null; // @D8 + // @EBD JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE, e); // @C1A + // @EBD } // @C1A + // @EBD catch (Exception e) { + // @EBD JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + // @EBD } + // @EBD } + + + + // @E5A + /** + Holds a request until the next explicit request. It will + be concatenated at the beginning of the next request. + + @param request The request. + @param id The id. + + @exception SQLException If an error occurs. + **/ + // + // See implementation notes for sendAndReceive(). + // + void sendAndHold(DBBaseRequestDS request, int id) + throws SQLException + { + checkCancel(); // @E8A + checkOpen(); // @W1a + + try + { + // Since we are just calling send() (instead of sendAndReceive()), // @EAA + // make sure we are not asking the system for a reply. Otherwise, // @EAA + // the reply will come back and it will get held in the AS400 // @EAA + // read daemon indefinitely - - a memory leak. // @EAA + if (JDTrace.isTraceOn()) + { // @EAA + if (request.getOperationResultBitmap() != 0) // @EAA + JDTrace.logInformation (this, "Reply requested but not collected:" + request.getReqRepID()); // @EAA + } // @EAA + + request.setBasedOnORSHandle(0); // @DAC @EKC + + if (dataCompression_ == DATA_COMPRESSION_RLE_) + { // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REQUEST_RLE_COMPRESSION); // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REPLY_RLE_COMPRESSION); // @ECA + request.compress(); // @ECA + } // @ECA + + synchronized(heldRequestsLock_) + { + if (heldRequests_ == null) + heldRequests_ = new Vector(); + heldRequests_.addElement(request); + } + + //@P0D requestPending_.set(id); // @DAC +//@P1D requestPending_[id] = true; //@P0A + + if (DEBUG_COMM_TRACE_ > 0) + { + debug (request); + System.out.println("This request was HELD."); + } + } + // Note: No need to check for an IOException in this method, since we don't contact the system. @J5A + catch (Exception e) + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + } + + + + /** + Sends a request data stream to the system using the + connection's id and returns the corresponding reply from + the system. + + @param request The request. + @return The reply. + + @exception SQLException If an error occurs. + **/ + // + // See implementation notes for sendAndReceive(). + // + DBReplyRequestedDS sendAndReceive (DBBaseRequestDS request) + throws SQLException + { + return sendAndReceive (request, id_); + } + + + + /** + Sends a request data stream to the system and returns the + corresponding reply from the system. + + @param request The request. + @param id The id. + @return The reply. + + @exception SQLException If an error occurs. + **/ + // + // Implementation notes: + // + // 1. We do not have to worry about thread synchronization + // here, since the AS400Server object handles it. + // + // 2. The based on id is used to chain requests for the + // same ORS without needing to get a reply for each one. + // If a request fails, then all subsequent requests will + // too, and the results from the original failure will + // ultimately be returned. + // + // Initially, the based on id is set to 0. After a + // request is sent the based on id is set to the statement's + // id, so that subsequent requests will base on this id. + // Finally, when a reply is retrieved, the based on id + // is reset to 0. + // + // The status of the based on id depends on whether a + // request is pending, which is maintained in the id table. + // + DBReplyRequestedDS sendAndReceive (DBBaseRequestDS request, int id) + throws SQLException + { + checkCancel(); // @E8A + checkOpen(); // @W1a + + DBReplyRequestedDS reply = null; + + try + { + request.setBasedOnORSHandle (0); // @DAC @EKC + + if (dataCompression_ == DATA_COMPRESSION_RLE_) + { // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REQUEST_RLE_COMPRESSION); // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REPLY_RLE_COMPRESSION); // @ECA + request.compress(); // @ECA + } // @ECA + + DataStream actualRequest; // @E5A + synchronized(heldRequestsLock_) + { // @E5A + if (heldRequests_ != null) // @E5A + actualRequest = new DBConcatenatedRequestDS(heldRequests_, request); // @E5A + else // @E5A + actualRequest = request; // @E5A + heldRequests_ = null; // @E5A + + reply = (DBReplyRequestedDS)server_.sendAndReceive(actualRequest); // @E5C @F7M + //@P0D requestPending_.clear(id); +//@P1D requestPending_[id] = false; //@P0A @F7M + } // @E5A + + reply.parse(dataCompression_); // @E5A + // @DAC + + if (DEBUG_COMM_TRACE_ > 0) + { + debug (request); + debug (reply); + } + } + // @J5D catch (ConnectionDroppedException e) { // @C1A + // @J5D server_ = null; // @D8 + // @J5D request.freeCommunicationsBuffer(); // @EMa + // @J5D JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE, e); // @C1A + // @J5D } // @C1A + catch (IOException e) + { // @J5A + server_ = null; // @J5A + //@P0D request.freeCommunicationsBuffer(); // @J5A + JDError.throwSQLException (this, JDError.EXC_COMMUNICATION_LINK_FAILURE, e); // @J5A + } // @J5A + catch (Exception e) + { + //@P0D request.freeCommunicationsBuffer(); // @EMa + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + + // if (DBDSPool.monitor) { + // reply.setAllocatedLocation(); + // } + + return(DBReplyRequestedDS) reply; + } + + + //@D2A + DBReplyRequestedDS sendAndMultiReceive (DBBaseRequestDS request) + throws SQLException + { + checkCancel(); // @E8A + checkOpen(); // @W1a + + DBReplyRequestedDS reply = null; + + try + { + request.setBasedOnORSHandle (0); // @DAC @EKC + + if (dataCompression_ == DATA_COMPRESSION_RLE_) + { // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REQUEST_RLE_COMPRESSION); // @ECA + request.addOperationResultBitmap(DBBaseRequestDS.ORS_BITMAP_REPLY_RLE_COMPRESSION); // @ECA + request.compress(); // @ECA + } // @ECA + + DataStream actualRequest; // @E5A + synchronized(heldRequestsLock_) + { // @E5A + if (heldRequests_ != null) // @E5A + actualRequest = new DBConcatenatedRequestDS(heldRequests_, request); // @E5A + else // @E5A + actualRequest = request; // @E5A + heldRequests_ = null; // @E5A + //D2A- allowed correlation ID to be stored and used on multiple receive calls + correlationID_ = server_.send(actualRequest); + reply = (DBReplyRequestedDS)server_.receive(correlationID_); + } // @E5A + + reply.parse(dataCompression_); // @E5A + // @DAC + + if (DEBUG_COMM_TRACE_ > 0) + { + debug (request); + debug (reply); + } + } + // @J5D catch (ConnectionDroppedException e) { // @C1A + // @J5D server_ = null; // @D8 + // @J5D request.freeCommunicationsBuffer(); // @EMa + // @J5D JDError.throwSQLException (this, JDError.EXC_CONNECTION_NONE, e); // @C1A + // @J5D } // @C1A + catch (IOException e) + { // @J5A + server_ = null; // @J5A + //@P0D request.freeCommunicationsBuffer(); // @J5A + JDError.throwSQLException (this, JDError.EXC_COMMUNICATION_LINK_FAILURE, e); // @J5A + } // @J5A + catch (Exception e) + { + //@P0D request.freeCommunicationsBuffer(); // @EMa + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + + return(DBReplyRequestedDS) reply; + } + + //@DA2 - sew added new receive method. + DBReplyRequestedDS receiveMoreData() + throws SQLException{ + DBReplyRequestedDS reply = null; + try{ + if(correlationID_ > 0){ + synchronized(heldRequestsLock_) + { + reply = (DBReplyRequestedDS)server_.receive(correlationID_); + } + reply.parse(dataCompression_); + } + }catch (Exception e) + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + return reply; + } + + + // @E4C + /** + Sets the auto-commit mode. If the connection is in auto-commit + mode, then all of its SQL statements are executed and committed + as individual transactions. Otherwise, its SQL statements are + grouped into transactions that are terminated by either a commit + or rollback. + +

By default, the connection is in auto-commit mode. The + commit occurs when the statement execution completes or the + next statement execute occurs, whichever comes first. In the + case of statements returning a result set, the statement + execution completes when the last row of the result set has + been retrieved or the result set has been closed. In advanced + cases, a single statement may return multiple results as well + as output parameter values. Here the commit occurs when all results + and output parameter values have been retrieved. + +

The auto-commit mode is always false when the connection is part + of a distributed transaction. See + AS400JDBCXAResource for more information. + + @param autoCommit true to turn on auto-commit mode, false to + turn it off. + + @exception SQLException If the connection is not open + or an error occurs. + **/ + public void setAutoCommit (boolean autoCommit) + throws SQLException + { + checkOpen (); + if (TESTING_THREAD_SAFETY) return; // in certain testing modes, don't contact IBM i system + + transactionManager_.setAutoCommit (autoCommit); + + if (JDTrace.isTraceOn()) + JDTrace.logProperty (this, "Auto commit", transactionManager_.getAutoCommit ()); + } + + + + /** + This method is not supported. + + @exception SQLException If the connection is not open. + **/ + public void setCatalog (String catalog) + throws SQLException + { + checkOpen (); + + // No-op. + } + + //@cc1 + /** + * This method sets concurrent access resolution. This method overrides the setting of ConcurrentAccessResolution on the datasource or connection + * URL properties. This changes the setting for this connection only. This method has no effect on + * IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @param concurrentAccessResolution The current access resolution setting. Possible valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public void setConcurrentAccessResolution (int concurrentAccessResolution) throws SQLException + { + + DBSQLAttributesDS request = null; + DBReplyRequestedDS reply = null; + try + { + if (getVRM() >= JDUtilities.vrm710) + { + request = DBDSPool.getDBSQLAttributesDS(DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); + + //get value of concurrent access resolution. + int car = properties_.getInt(JDProperties.CONCURRENT_ACCESS_RESOLUTION); + //here, we also allow resetting back to default 0 + //pass value of concurrent access resolution into the hostserver request. + request.setConcurrentAccessResolution( car ); + + reply = sendAndReceive(request); + int errorClass = reply.getErrorClass(); + if (errorClass != 0) + JDError.throwSQLException(this, id_, errorClass, reply.getReturnCode()); + } + } catch( Exception e) + { + JDError.throwSQLException( this, JDError.EXC_INTERNAL, e); + } finally + { + if (request != null) { + request.returnToPool(); request=null; + } + if (reply != null) { + reply.returnToPool(); reply = null; // Can return -- only errorClass accessed + } + } + + concurrentAccessResolution_ = concurrentAccessResolution; + } + + + /** + Sets the eWLM Correlator. It is assumed a valid correlator value is used. + If the value is null, all ARM/eWLM implementation will be turned off. + eWLM correlators require IBM i V5R3 or later systems. This request is ignored when running to OS/400 V5R2 or earlier systems. + + @param bytes The eWLM correlator value + **/ + public void setDB2eWLMCorrelator(byte[] bytes) + throws SQLException //@eWLM + { + if(vrm_ >= JDUtilities.vrm530) + { + DBSQLAttributesDS request = null; + DBReplyRequestedDS reply = null; + try + { + if(bytes == null) + { + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Correlator is null"); + } + request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, + id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); + request.seteWLMCorrelator(bytes); + reply = sendAndReceive(request); + int errorClass = reply.getErrorClass(); + if(errorClass != 0) + JDError.throwSQLException(this, id_, errorClass, reply.getReturnCode()); + } + catch(DBDataStreamException e) + { + JDError.throwSQLException(JDError.EXC_INTERNAL, e); + } + finally + { + if (request != null) { request.returnToPool(); request = null; } + if (reply != null) { reply.returnToPool(); reply = null; } // Return to pool since only errorClass accessed + } + } + } + + + // @B1A + /** + Sets whether the connection is being used for DRDA. + + @param drda true if the connection is being used for DRDA, + false otherwise. + **/ + void setDRDA (boolean drda) + throws SQLException // @EGA + { + drda_ = drda; + + if (JDTrace.isTraceOn()) + JDTrace.logProperty (this, "DRDA", drda_); + } + + + //@G4A JDBC 3.0 + /** + Sets the holdability of ResultSets created from this connection. + +

Full functionality of this method requires OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, all + cursors for the connection will be changed to the value of the variable + holdability. + + @param holdability The cursor holdability. + Valid values are ResultSet.HOLD_CURSORS_OVER_COMMIT or + ResultSet.CLOSE_CURSORS_AT_COMMIT. + + @exception SQLException If the connection is not open + or the value passed in is not valid. + @since Modification 5 + **/ + public void setHoldability (int holdability) + throws SQLException + { + checkOpen (); + if (TESTING_THREAD_SAFETY) return; // in certain testing modes, don't contact IBM i system + + if (!checkHoldabilityConstants(holdability)) //@F3A + JDError.throwSQLException (this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); //@F3A + + holdability_ = holdability; + + if (holdability == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT) //@F5A + transactionManager_.setHoldIndicator(JDProperties.CURSORHOLD_FALSE); //@F5A + else if (holdability == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) //@F5A + transactionManager_.setHoldIndicator(JDProperties.CURSORHOLD_TRUE); //@F5A + + if (JDTrace.isTraceOn()) + JDTrace.logProperty (this, "Holdability", holdability_); + } + + + + //@D4A + void setProperties (JDDataSourceURL dataSourceUrl, JDProperties properties, + AS400 as400) + throws SQLException + { + if (TESTING_THREAD_SAFETY) // in certain testing modes, don't contact IBM i system + { + as400PublicClassObj_ = as400; + } + else + { + try + { + as400.connectService (AS400.DATABASE); + } + catch (AS400SecurityException e) + { //@D5C + JDError.throwSQLException (this, JDError.EXC_CONNECTION_REJECTED, e); + } + catch (IOException e) + { //@D5C + JDError.throwSQLException (this, JDError.EXC_CONNECTION_UNABLE, e); + } + finally //@dbldrvr + { //@dbldrvr + //Since driver is registered twice in DriverManager via DriverManager.registerDriver(new AS400JDBCDriver()), + //remove extra driver references now so we don't waste resources by continuing to try, and also so we don't lock out id if pwd is not correct. + Enumeration en = DriverManager.getDrivers(); //@dbldrvr + Driver firstDriver = null; //@dbldrvr + Driver nextDriver = null; //@dbldrvr + while (en.hasMoreElements()) //@dbldrvr + { //@dbldrvr + nextDriver = (Driver) en.nextElement(); //@dbldrvr + if(nextDriver instanceof AS400JDBCDriver) //@dbldrvr + { //@dbldrvr + if(firstDriver == null) //@dbldrvr + firstDriver = nextDriver; //@dbldrvr + else //@dbldrvr + DriverManager.deregisterDriver(nextDriver); //@dbldrvr + } //@dbldrvr + } //@dbldrvr + } //@dbldrvr + } + + setProperties (dataSourceUrl, properties, as400.getImpl()); + } + + + void setProperties(JDDataSourceURL dataSourceUrl, JDProperties properties, AS400Impl as400) + throws SQLException + { + setProperties(dataSourceUrl, properties, as400, false); + } + + //@A3A - This logic formerly resided in the ctor. + void setProperties (JDDataSourceURL dataSourceUrl, JDProperties properties, AS400Impl as400, boolean newServer) + throws SQLException + { + // Initialization. + as400_ = (AS400ImplRemote) as400; //@A3A + //@P0D assigned_ = new BitSet(INITIAL_STATEMENT_TABLE_SIZE_); // @DAC + dataSourceUrl_ = dataSourceUrl; + extendedFormats_ = false; + properties_ = properties; + //Set the real default for METADATA SOURCE property since we now know the hostsrvr version + if(properties_.getString(JDProperties.METADATA_SOURCE).equals(JDProperties.METADATA_SOURCE_HOST_VERSION_DEFAULT)) //@mdsp + { //@mdsp + if(as400_.getVRM() < JDUtilities.vrm710) //@mdsp //@710 take effect after 710 (ie. not 615) + properties_.setString(JDProperties.METADATA_SOURCE, JDProperties.METADATA_SOURCE_ROI); //@mdsp + else //@mdsp + properties_.setString(JDProperties.METADATA_SOURCE, JDProperties.METADATA_SOURCE_STORED_PROCEDURE); //@mdsp + } //@mdsp + + //@P0D requestPending_ = new BitSet(INITIAL_STATEMENT_TABLE_SIZE_); // @DAC + statements_ = new Vector(INITIAL_STATEMENT_TABLE_SIZE_); // @DAC + if(!TESTING_THREAD_SAFETY && as400_.getVRM() <= JDUtilities.vrm520) //@KBA //if V5R2 or less use old support of issuing set transaction statements + newAutoCommitSupport_ = 0; //@KBA + else if(!properties_.getBoolean(JDProperties.TRUE_AUTO_COMMIT)) //@KBA //@true //run autocommit with *NONE isolation level + newAutoCommitSupport_ = 1; //@KBA + else //@KBA + newAutoCommitSupport_ = 2; //@KBA //run autocommit with specified isolation level + + + if (as400_.getVRM() >= JDUtilities.vrm710) { + doUpdateDeleteBlocking_ = properties_.getBoolean(JDProperties.DO_UPDATE_DELETE_BLOCKING); //@A2A + } + + maximumBlockedInputRows_ = properties_.getInt(JDProperties.MAXIMUM_BLOCKED_INPUT_ROWS); // @A6A + if ( maximumBlockedInputRows_ > 32000 ) maximumBlockedInputRows_ = 32000; // @A6A + if ( maximumBlockedInputRows_ < 1 ) maximumBlockedInputRows_ = 1; // @A6A + + // Issue any warnings. + if (dataSourceUrl_.isExtraPathSpecified ()) + postWarning (JDError.getSQLWarning (JDError.WARN_URL_EXTRA_IGNORED)); + if (dataSourceUrl_.isPortSpecified ()) + postWarning (JDError.getSQLWarning (JDError.WARN_URL_EXTRA_IGNORED)); + if (properties.isExtraPropertySpecified ()) + postWarning (JDError.getSQLWarning (JDError.WARN_PROPERTY_EXTRA_IGNORED)); + + // Initialize the library list. + String urlSchema = dataSourceUrl_.getSchema (); + if (urlSchema == null) + JDError.throwSQLException (this, JDError.WARN_URL_SCHEMA_INVALID); + + JDLibraryList libraryList = new JDLibraryList ( + properties_.getString (JDProperties.LIBRARIES), urlSchema, + properties_.getString (JDProperties.NAMING)); // @B2C + defaultSchema_ = libraryList.getDefaultSchema (); + + // The connection gets an id automatically, but never + // creates an RPB on the system. There should never be a need + // to create an RPB on the system for a connection, but an + // id is needed for retrieving Operational Result Sets (ORS) + // for errors, etc. + + // Initialize a transaction manager for this connection. + transactionManager_ = new JDTransactionManager (this, id_, + properties_.getString (JDProperties.TRANSACTION_ISOLATION), + properties_.getBoolean (JDProperties.AUTO_COMMIT)); //@AC1 + + transactionManager_.setHoldIndicator(properties_.getString(JDProperties.CURSOR_HOLD)); // @D9 + + // If the hold properties are specified, make sure they are set locally + if (properties_.getString(JDProperties.CURSOR_HOLD) != null) { + if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_TRUE) + holdability_ = AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT; + else if (transactionManager_.getHoldIndicator() == JDTransactionManager.CURSOR_HOLD_FALSE) + holdability_ = AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + // Initialize the read-only mode to true if the access + // property says read only. + readOnly_ = (properties_.equals (JDProperties.ACCESS, + JDProperties.ACCESS_READ_ONLY)); + + + // Determine the amount of system tracing that should be started. Trace + // can be started by either a JDBC property or the ServerTrace class. Our value + // will be the combination of the two (instead of one overriding the other). + traceServer_ = properties_.getInt(JDProperties.TRACE_SERVER) | + ServerTrace.getJDBCServerTraceCategories(); // @j1a //@SSa logical OR + + // Determine if a QAQQINI library name was specified. The library can be set using //@K2A + // a JDBC property. //@k2A + qaqqiniLibrary_ = properties_.getString(JDProperties.QAQQINILIB); //@K2A + + + String queryTimeoutMechanismString = properties_.getString(JDProperties.QUERY_TIMEOUT_MECHANISM); + if (queryTimeoutMechanismString != null) { + queryTimeoutMechanismString = queryTimeoutMechanismString.trim().toLowerCase(); + if (queryTimeoutMechanismString.equals(JDProperties.QUERY_TIMEOUT_MECHANISM_CANCEL)) { + queryTimeoutMechanism_ = QUERY_TIMEOUT_CANCEL; + } else { + queryTimeoutMechanism_ = QUERY_TIMEOUT_QQRYTIMLMT; + } + } + //@A3D + // Initialize the conversation. + //open (); + + //@A3A + // Connect. + if (JDTrace.isTraceOn()) // @F6a + { // @F6a + JDTrace.logInformation("Toolbox for Java - " + Copyright.version); // @F6a + JDTrace.logInformation("JDBC Level: " + JDUtilities.JDBCLevel_); // @F6a + } // @F6a + + if (!TESTING_THREAD_SAFETY) // in certain testing modes, we don't contact IBM i system + { + try + { + server_ = as400_.getConnection (AS400.DATABASE, newServer); + } + catch (AS400SecurityException e) + { + JDError.throwSQLException (this, JDError.EXC_CONNECTION_REJECTED, e); + } + catch (IOException e) + { + JDError.throwSQLException (this, JDError.EXC_CONNECTION_UNABLE, e); + } + } + + // Initialize the catalog name at this point to be the system + // name. After we exchange attributes, we can change it to + // the actual name. + catalog_ = dataSourceUrl.getServerName(); // @D7A + if (catalog_.length() == 0) // @D7A + catalog_ = as400_.getSystemName ().toUpperCase (); // @A3A + + setServerAttributes (); + libraryList.addOnServer (this, id_); + + // @E7D // Initialize a transaction manager for this connection. Turn on @E7A + // @E7D // new auto-commit support when the server functional level is @E7A + // @E7D // greater than or equal to 3. @E7A + // @E7D boolean newAutoCommitSupport = (serverFunctionalLevel_ >= 3); // @E7A + // @E7D transactionManager_.setNewAutoCommitSupport(newAutoCommitSupport); // @E7A + + // We keep a metadata object around for quick access. + // The metadata object should share the id of the + // connection, since it operates on a connection-wide + // scope. + metaData_ = new AS400JDBCDatabaseMetaData (this, id_); + + // The conversation was initialized to a certain + // transaction isolation. It is now time to turn on auto- + // commit by default. + if(newAutoCommitSupport_ == 0) //KBA V5R2 or less so do what we always have + transactionManager_.setAutoCommit (true); + + // Initialize the package manager. + packageManager_ = new JDPackageManager (this, id_, properties_, + transactionManager_.getCommitMode ()); + + // Trace messages. + if (JDTrace.isTraceOn()) + { + JDTrace.logOpen (this, null); // @J33a + JDTrace.logProperty (this, "Auto commit", transactionManager_.getAutoCommit ()); + JDTrace.logProperty (this, "Read only", readOnly_); + JDTrace.logProperty (this, "Transaction isolation", transactionManager_.getIsolation ()); + if (packageManager_.isEnabled ()) + JDTrace.logInformation (this, "SQL package = " + + packageManager_.getLibraryName() + "/" + + packageManager_.getName ()); + } + + + // @j1a Trace the server job if the user asked us to. Tracing + // can be turned on via a URL property, the Trace class, the DataSource + // object, or a system property. + if (traceServer_ > 0) + { + // Get the server job id. We will both dump this to the trace + // and use it to uniquely label some of the files. + String serverJobIdentifier = getServerJobIdentifier(); + String serverJobId = serverJobIdentifier.substring(20).trim() + "/" + + serverJobIdentifier.substring(10, 19).trim() + "/" + + serverJobIdentifier.substring( 0, 10).trim(); + + // Dump the server job id + JDTrace.logDataEvenIfTracingIsOff(this, Copyright.version); + JDTrace.logDataEvenIfTracingIsOff(this, serverJobId); + JDTrace.logDataEvenIfTracingIsOff(this, "Server functional level: " + getServerFunctionalLevel()); // @E7A + + + // Determine system level. Some commands are slightly different + // to v5r1 machines. + boolean preV5R1 = true; + boolean SQLNaming = properties_.getString(JDProperties.NAMING).equals(JDProperties.NAMING_SQL); + try + { + preV5R1 = getVRM() <= JDUtilities.vrm450; + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job tracing failed, could not get server VRM"); + } + + // Start client tracing if the flag is on and trace isn't already running + if (((traceServer_ & ServerTrace.JDBC_TRACE_CLIENT) > 0) && (! JDTrace.isTraceOn())) + JDTrace.setTraceOn(true); + + // No matter what type of tracing is turned on, alter the server + // job so more stuff is saved in the job log. + try + { + JDUtilities.runCommand(this, "QSYS/CHGJOB LOG(4 00 *SECLVL) LOGCLPGM(*YES)", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job tracing failed, could not change log level"); + } + + // Optionally start debug on the database server job + if ((traceServer_ & ServerTrace.JDBC_DEBUG_SERVER_JOB) > 0) + { + try + { + JDUtilities.runCommand(this, "QSYS/STRDBG UPDPROD(*YES)", SQLNaming); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job tracing failed, could not start debug on server job "); + } + } + + // Optionally start the database monitor + if ((traceServer_ & ServerTrace.JDBC_START_DATABASE_MONITOR) > 0) + { + try + { + JDUtilities.runCommand(this, "QSYS/STRDBMON OUTFILE(QUSRSYS/QJT" + + serverJobIdentifier.substring(20) + + ") JOB(*) TYPE(*DETAIL)", SQLNaming ); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job tracing failed, could not start database monitor"); + } + } + + boolean traceServerJob = ((traceServer_ & ServerTrace.JDBC_TRACE_SERVER_JOB) > 0); //@540 + //@540 Database Host Server Trace is supported on V5R3 and later systems + boolean traceDatabaseHostServer = ((getVRM() >= JDUtilities.vrm530) && ((traceServer_ & ServerTrace.JDBC_TRACE_DATABASE_HOST_SERVER) > 0)); //@540 + // Optionally start trace on the database server job or database host server + //@540D if ((traceServer_ & ServerTrace.JDBC_TRACE_SERVER_JOB) > 0) + if(traceServerJob || traceDatabaseHostServer) //@540 + { + try + { + if (preV5R1 && traceServerJob) //@540 added check for traceServerJob + JDUtilities.runCommand(this, "QSYS/TRCJOB MAXSTG(16000)", SQLNaming); + else{ + if(!traceDatabaseHostServer){ //@540 trace only server job + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") JOB(*) MAXSTG(128000)", SQLNaming); + } + else if(!traceServerJob){ //@540 trace only database host server + if(getVRM() == JDUtilities.vrm530){ //@540 run command for V5R3 + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + //@540 + serverJobIdentifier.substring(20) + //@540 + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*TRCTYPE) " + //@540 + "TRCTYPE((TESTA *INFO))", SQLNaming); //@540 + } + else{ //@540 run command for V5R4 and higher + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + //@540 + serverJobIdentifier.substring(20) + //@540 + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*TRCTYPE) " + //@540 + "TRCTYPE((*DBHSVR *INFO))", SQLNaming); //@540 + } + } //@540 + else{ //@540 start both server job and database host server trace + if(getVRM() == JDUtilities.vrm530){ //@540 run command for V5R3 + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + //@540 + serverJobIdentifier.substring(20) + //@540 + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*ALL) " + //@540 + "TRCTYPE((TESTA *INFO))", SQLNaming); //@540 + } + else{ //@540 run V5R4 and higher command + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + //@540 + serverJobIdentifier.substring(20) + //@540 + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*ALL) " + //@540 + "TRCTYPE((*DBHSVR *INFO))", SQLNaming); //@540 + } + } + } + } + catch (Exception e) + { + if(traceServerJob && !traceDatabaseHostServer) //@540 + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job tracing failed, could not trace server job"); + else if(traceDatabaseHostServer && !traceServerJob) //@540 + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start database host server tracing failed, could not trace server job"); //@540 + else //@540 + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start server job and database host server tracing failed, could not trace server job"); //@540 + } + } + } + + //@K2A Issue Change Query Attributes command if user specified QAQQINI library name + if(qaqqiniLibrary_.length() > 0 && !qaqqiniLibrary_.equals("null")) + { + boolean SQLNaming = properties_.getString(JDProperties.NAMING).equals(JDProperties.NAMING_SQL); + try + { + JDUtilities.runCommand(this, "CHGQRYA QRYOPTLIB(" + qaqqiniLibrary_ + ")", SQLNaming ); + } + catch (Exception e) + { + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to issue Change Query Attributes command using QAQQINI Library name failed."); + } + } + } + + + + /** + Sets the read-only mode. This will provide read-only + access to the database. Read-only mode can be useful by + enabling certain database optimizations. If the caller + specified "read only" or "read call" for the "access" property, + then the read-only mode cannot be set to false. The read-only + mode cannot be changed while in the middle of a transaction. + +

This method can not be called when the connection is part + of a distributed transaction. See + AS400JDBCXAResource for more information. + + @exception SQLException If the connection is not open, + a transaction is active, or the + "access" property is set to "read + only". + **/ + public void setReadOnly (boolean readOnly) + throws SQLException + { + checkOpen (); + + if (transactionManager_.isLocalActive () || transactionManager_.isGlobalActive()) // @E4C + JDError.throwSQLException (this, JDError.EXC_TXN_STATE_INVALID); // @E4C + + if ((readOnly == false) + && ((properties_.getString (JDProperties.ACCESS).equalsIgnoreCase (JDProperties.ACCESS_READ_ONLY)) + || (properties_.getString (JDProperties.ACCESS).equalsIgnoreCase (JDProperties.ACCESS_READ_CALL)))) + JDError.throwSQLException (this, JDError.EXC_ACCESS_MISMATCH); + + readOnly_ = readOnly; + + if (JDTrace.isTraceOn()) + JDTrace.logProperty (this, "Read only", readOnly_); + } + + + + + // @E10 new method + /** + * Creates an unnamed savepoint in the current transaction and returns the new Savepoint object that represents it. + *

+ * + * @return The new Savepoint object. + * @exception SQLException if a database access error occurs or this Connection object is currently in auto-commit mode. + * @since Modification 5 + **/ + public Savepoint setSavepoint() + throws SQLException + { + return setSavepoint(null, AS400JDBCSavepoint.getNextId()); + } + + // @E10 new method + /** + * Creates a named savepoint in the current transaction and returns the new Savepoint object that represents it. + * + * @param name A String containing the name of the savepoint + * @return The new Savepoint object. + * @exception SQLException if a database access error occurs or this Connection object is currently in auto-commit mode. + * @since Modification 5 + **/ + public Savepoint setSavepoint(String name) + throws SQLException + { + if (name == null) + throw new NullPointerException("name"); + + return setSavepoint(name, 0); + } + + // @E10 new method + private Savepoint setSavepoint(String name, int id) + throws SQLException + { + if (id > 0) + name = "T_JDBCINTERNAL_" + id; + + // When creating the savepoint specify retain cursors. That is the + // only option supported by the IBM i system at this time. We have to specify + // it because the SQL default is close cursors. Since we need to use + // an option other than the default we have to specify it on the statement. + // Plus, the system will return an error if we don't specify it. + processSavepointRequest("SAVEPOINT " + name + " ON ROLLBACK RETAIN CURSORS" ); + + return(Savepoint)(Object) new AS400JDBCSavepoint(name, id); + } + + + + + + + + /** + Sets the server attributes. + + @param libraryList The library list. + + @exception SQLException If an error occurs. + **/ + private void setServerAttributes () + throws SQLException + { + if (TESTING_THREAD_SAFETY) return; // in certain testing modes, don't contact IBM i system + DBReplyRequestedDS reply = null; + try + { + vrm_ = as400_.getVRM(); // @D0A @ECM + + //@P0C + DBSQLAttributesDS request = null; + int decimalSeparator, dateFormat, dateSeparator, timeFormat, timeSeparator; + int decimalDataErrors; + DBReplyServerAttributes serverAttributes = null; + try + { + request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, + id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@P0C + + // We need to set a temporary CCSID just for this + // request, since we use this request to get the + // actual CCSID. + //@P0D ConverterImplRemote tempConverter = + //@P0D ConverterImplRemote.getConverter (as400_.getCcsid(), as400_); + ConvTable tempConverter = ConvTable.getTable(as400_.getCcsid(), null); //@P0A + + + // @E2D // Do not set the client CCSID. We do not want + // @E2D // the system to convert data, since we are going + // @E2D // to do all conersion on the client. By not telling + // @E2D // the system our CCSID, then we achieve this. + // @E2D // + // @E2D // Note that the database host server documentation + // @E2D // states that when we do this, the CCSID values + // @E2D // in data formats may be incorrect and that we + // @E2D // should always use the server job's CCSID. + + // Set the client CCSID to Unicode. // @E2A + + // @M0C - As of v5r3m0 we allow the client CCSID to be 1200 (UTF-16) which + // will cause our statement to flow in 1200 and our package to be 1200 + + //Bidi-HCG allow any ccsid or "system" to use ccsid of AS400 object + //Bidi-HCG start + String sendCCSID = properties_.getString(JDProperties.PACKAGE_CCSID); + + int sendCCSIDInt; + int hostCCSID; + if(this.getSystem() == null) //@pdcbidi + hostCCSID = 37; + else + hostCCSID = this.getSystem().getCcsid(); + int default_ccsid = Integer.parseInt(JDProperties.PACKAGE_CCSID_UCS2); + + if( sendCCSID.equalsIgnoreCase("system")) + sendCCSIDInt = hostCCSID; + else { + try{ + if((sendCCSIDInt = Integer.valueOf(sendCCSID).intValue()) <= 0) + sendCCSIDInt = default_ccsid; + if(vrm_ < JDUtilities.vrm530 && sendCCSIDInt == 1200) + sendCCSIDInt = default_ccsid; + } catch(Exception e) { + sendCCSIDInt = default_ccsid; + } + } + + packageCCSID_Converter = ConvTable.getTable(sendCCSIDInt, null); + properties_.setString(JDProperties.PACKAGE_CCSID, (new Integer(sendCCSIDInt)).toString()); + request.setClientCCSID(sendCCSIDInt); + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Client CCSID = " + sendCCSIDInt); + //Bidi-HCG end + + // This language feature code is used to tell the + // system what language to send error messages in. + // If that language is not installed on the system, + // we get messages back in the default language that + // was installed on the system. + // + String nlv = as400_.getNLV(); // @F1C + request.setLanguageFeatureCode(nlv); // @EDC + + if (JDTrace.isTraceOn ()) + JDTrace.logInformation (this, "Setting server NLV = " + nlv); + + // Client functional level. + request.setClientFunctionalLevel(CLIENT_FUNCTIONAL_LEVEL_); // @EDC + + if (JDTrace.isTraceOn ()) // @EDC + JDTrace.logInformation (this, "Client functional level = " + CLIENT_FUNCTIONAL_LEVEL_); // @EDC + + // Sort sequence. + if (! properties_.equals (JDProperties.SORT, JDProperties.SORT_HEX)) //@pdc only send if not default (hex) + { + JDSortSequence sortSequence = new JDSortSequence ( + properties_.getString (JDProperties.SORT), + properties_.getString (JDProperties.SORT_LANGUAGE), + properties_.getString (JDProperties.SORT_TABLE), + properties_.getString (JDProperties.SORT_WEIGHT)); + request.setNLSSortSequence (sortSequence.getType (), + sortSequence.getTableFile (), + sortSequence.getTableLibrary (), + sortSequence.getLanguageId (), + tempConverter); + } + + request.setTranslateIndicator (0xF0); // @E2C + request.setDRDAPackageSize (1); + //Note: newAutoCommitSupport is trueAutoCommitSupport + if(!(newAutoCommitSupport_ == 0)) //@KBA V5R3 or greater so run with new support + { //@AC1 + if(properties_.getBoolean(JDProperties.AUTO_COMMIT)) //@AC1 + request.setAutoCommit(0xE8); //@KBA Turn on auto commit + else //@AC1 + request.setAutoCommit(0xD5); //@AC1 + } //@AC1 + + if((newAutoCommitSupport_ == 1) && (properties_.getBoolean(JDProperties.AUTO_COMMIT))) //@KBA //@AC1 (only set to *NONE if autocommit is on) + request.setCommitmentControlLevelParserOption(0); //@KBA Run under *NONE when in autocommit + else //@KBA Run under default isolation level + request.setCommitmentControlLevelParserOption (transactionManager_.getCommitMode ()); + + // Server attributes based on property values. + // These all match the index within the property's + // choices. + dateFormat = properties_.getIndex (JDProperties.DATE_FORMAT); + if (dateFormat != -1) + request.setDateFormatParserOption (dateFormat); + + dateSeparator = properties_.getIndex (JDProperties.DATE_SEPARATOR); + if (dateSeparator != -1) + request.setDateSeparatorParserOption (dateSeparator); + + timeFormat = properties_.getIndex (JDProperties.TIME_FORMAT); + if (timeFormat != -1) + request.setTimeFormatParserOption (timeFormat); + + timeSeparator = properties_.getIndex (JDProperties.TIME_SEPARATOR); + if (timeSeparator != -1) + request.setTimeSeparatorParserOption (timeSeparator); + + decimalSeparator = properties_.getIndex (JDProperties.DECIMAL_SEPARATOR); + if (decimalSeparator != -1) + request.setDecimalSeparatorParserOption (decimalSeparator); + + request.setNamingConventionParserOption (properties_.getIndex (JDProperties.NAMING)); + + // Set the ignore decimal data error parser option. + decimalDataErrors = properties_.getIndex (JDProperties.DECIMAL_DATA_ERRORS); + if (decimalDataErrors != -1) + request.setIgnoreDecimalDataErrorParserOption(decimalDataErrors); + + // If the system supports RLE data compression, then use it. @ECA + // Otherwise, use the old-style data compression. @ECA + if (properties_.getBoolean(JDProperties.DATA_COMPRESSION)) + { // @ECA + if (vrm_ >= JDUtilities.vrm510) + { // @ECA + dataCompression_ = DATA_COMPRESSION_RLE_; // @ECA + request.setDataCompressionOption(0); // @ECA + if (JDTrace.isTraceOn ()) // @ECA + JDTrace.logInformation (this, "Data compression = RLE"); // @ECA + } // @ECA + else + { // @ECA + dataCompression_ = DATA_COMPRESSION_OLD_; // @ECA + request.setDataCompressionOption(1); // @D3A @ECC + if (JDTrace.isTraceOn ()) // @ECA + JDTrace.logInformation (this, "Data compression = old"); // @ECA + } // @ECA + } // @ECA + else + { // @ECA + dataCompression_ = DATA_COMPRESSION_NONE_; // @ECA + request.setDataCompressionOption(0); // @ECA + if (JDTrace.isTraceOn ()) // @ECA + JDTrace.logInformation (this, "Data compression = none"); // @ECA + } // @ECA + + // Default SQL schema. + if (defaultSchema_ != null) + request.setDefaultSQLLibraryName (defaultSchema_, tempConverter); + + // There is no need to tell the system what our code + // page is, nor is there any reason to get a translation + // table back from the system at this point. This + // will be handled later by the Converter class. + + // I haven't found a good reason to set the ambiguous select + // option. ODBC sets it only when block criteria is "unless + // FOR UPDATE OF", but it causes some problems for JDBC. + // The difference is that ODBC has the luxury of setting cursor + // concurrency. + + request.setPackageAddStatementAllowed (properties_.getBoolean (JDProperties.PACKAGE_ADD) ? 1 : 0); + + // If the system is at V4R4 or later, then set some more attributes. + if (vrm_ >= JDUtilities.vrm440) + { // @D0C @E9C + // @E9D || (FORCE_EXTENDED_FORMATS_)) { + + if(vrm_ >= JDUtilities.vrm540) //@540 use new Super Extended Formats + request.setUseExtendedFormatsIndicator(0xF2); //@540 + else //@540 + request.setUseExtendedFormatsIndicator (0xF1); + + // Although we publish a max lob threshold of 16777216, @E6A + // the system can only handle 15728640. We do it this @E6A + // way to match ODBC. @E6A + int lobThreshold = properties_.getInt (JDProperties.LOB_THRESHOLD); // @E6A + if (lobThreshold <= 0) // @E6A + request.setLOBFieldThreshold(0); // @E6A + else if (lobThreshold >= 15728640) // @E6A + request.setLOBFieldThreshold(15728640); // @E6A + else // @E6A + request.setLOBFieldThreshold(lobThreshold); // @E6C + + extendedFormats_ = true; + } + + // Set the default select statement type to be read-only (OS/400 v5r1 + // and earlier the default was updatable). If the app requests updatable + // statements we will now specify "updatable" on the RPB. Do this + // only to V5R1 systems with the needed PTF, and V5R2 and later systems + // because they have the fix needed to support + // altering the cursor type in the RPB. (AmbiguousSelectOption(1) + // means read-only) + if (vrm_ >= JDUtilities.vrm520) // @J3a + { // @J3a + request.setAmbiguousSelectOption(1); // @J3a + mustSpecifyForUpdate_ = false; // @J31a + + if(vrm_ >= JDUtilities.vrm710){ //@710 //@128sch + //@710 - Client support information - indicate our support for ROWID data type, true autocommit + // and 128 byte column names and 128 length schemas + request.setClientSupportInformation(0xF0000000); + if(JDTrace.isTraceOn()){ + JDTrace.logInformation(this, "ROWID supported = true"); + JDTrace.logInformation(this, "True auto-commit supported = true"); + JDTrace.logInformation(this, "128 byte column names supported = true"); + JDTrace.logInformation(this, "128 length schema names supported = true"); + } + + } + else if(vrm_ >= JDUtilities.vrm540){ //@540 for IBM i V5R4 and later, 128 byte column names are supported + //@540 - Client support information - indicate our support for ROWID data type, true autocommit + // and 128 byte column names + request.setClientSupportInformation(0xE0000000); + if(JDTrace.isTraceOn()){ + JDTrace.logInformation(this, "ROWID supported = true"); + JDTrace.logInformation(this, "True auto-commit supported = true"); + JDTrace.logInformation(this, "128 byte column names supported = true"); + } + + } + else if (vrm_ >= JDUtilities.vrm530) //@KBA For IBM i V5R3 and later true auto commit support is supported. + { + // @KBA - Client support information - indicate our support for ROWID data type and + // true auto-commit + request.setClientSupportInformation(0xC0000000); //@KBC + if(JDTrace.isTraceOn()) //@KBA + { //@KBA + JDTrace.logInformation(this, "ROWID supported = true"); //@KBA + JDTrace.logInformation(this, "True auto-commit supported = true"); //@KBA + } //@KBA + } //@KBA + else //@KBA + { //@KBA + // @M0A - Client support information - indicate our support for ROWID data type + request.setClientSupportInformation(0x80000000); + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "ROWID supported = true"); + } //@KBA + } + + // @M0A - added support for 63 digit decimal precision + if(vrm_ >= JDUtilities.vrm530) + { + int maximumPrecision = properties_.getInt(JDProperties.MAXIMUM_PRECISION); + int maximumScale = properties_.getInt(JDProperties.MAXIMUM_SCALE); + int minimumDivideScale = properties_.getInt(JDProperties.MINIMUM_DIVIDE_SCALE); + + // make sure that if scale is >31 we set precision to 63 + // this is a requirement of host server to avoid a PWS0009 + if(maximumScale > 31) + maximumPrecision = 63; + + request.setDecimalPrecisionIndicators(maximumPrecision, maximumScale, minimumDivideScale); + + if(JDTrace.isTraceOn()) + { + JDTrace.logInformation(this, "Maximum decimal precision = " + maximumPrecision); + JDTrace.logInformation(this, "Maximum decimal scale = " + maximumScale); + JDTrace.logInformation(this, "Minimum divide scale = " + minimumDivideScale); + } + + // @M0A - added support of hex constant parser option + int parserOption = properties_.getIndex(JDProperties.TRANSLATE_HEX); + if(parserOption != -1) + { + request.setHexConstantParserOption(parserOption); + if(JDTrace.isTraceOn()) + { + String msg = (parserOption == 0) ? "Translate hex = character" : "Translate hex = binary"; + JDTrace.logInformation(this, msg); + } + } + + //@KBL - added support for hold/not hold locators + // Specifies whether input locators should be allocated as type hold locators or not hold locators. + // If the locators are of type hold, they will not be released when a commit is done. + boolean holdLocators = properties_.getBoolean(JDProperties.HOLD_LOCATORS); + if(!holdLocators) // Only need to set it if it is false, by default host server sets them to hold. + { + request.setInputLocatorType(0xD5); + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Hold Locators = " + holdLocators); + } + + //@KBL - added support for locator persistance. The JDBC specification says locators should be + // scoped to the transaction (ie. commit, rollback, or connection.close()) if auto commit is off + // host server added two options for the optional Locator Persistence ('3830'x') connection attribute: + // 0 -- Locators without the hold property are freed when cursor closed (locators scoped to the cursor). + // 1 -- Locators without the hold property are freed when the transaction is completed (locators scoped to the transaction). + // + // By default this is set to 0 by the host server, but to comply with the JDBC specification, + // we should always set it to 1. + // Note: this only applies when auto commit is off. The property has no effect if auto commit is on. + // Locators are always scoped to the cursor when auto-commit is on. + request.setLocatorPersistence(1); + } + + //@540 + if(vrm_ >= JDUtilities.vrm540){ + + //Set the query optimization goal + // 0 = Optimize query for first block of data (*ALLIO) when extended dynamic packages are used; Optimize query for entire result set (*FIRSTIO) when packages are not used (default) //@PDC update comment to reflect host server default + // 1 = Optimize query for first block of data (*FIRSTIO) + // 2 = Optimize query for entire result set (*ALLIO) + int queryOptimizeGoal = properties_.getInt (JDProperties.QUERY_OPTIMIZE_GOAL); + if(queryOptimizeGoal != 0){ // Only need to send if we are not using the default + if(queryOptimizeGoal == 1) + request.setQueryOptimizeGoal(0xC6); + else if(queryOptimizeGoal == 2) + request.setQueryOptimizeGoal(0xC1); + } + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "query optimize goal = " + queryOptimizeGoal); + } + + //@550 Query Storage Limit Support + if(vrm_ >= JDUtilities.vrm610){ + //Set the query storage limit + int queryStorageLimit = properties_.getInt(JDProperties.QUERY_STORAGE_LIMIT); + if(queryStorageLimit != -1) // Only need to send if we are not using the default of *NOMAX (-1) + { + if(queryStorageLimit < -1) + request.setQueryStorageLimit(-1); + else if(queryStorageLimit > AS400JDBCDataSource.MAX_STORAGE_LIMIT) // if larger than the max just set to max + request.setQueryStorageLimit(2147352578); + else + request.setQueryStorageLimit(queryStorageLimit); + } + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "query storage limit = " + queryStorageLimit); + } + + if (JDTrace.isTraceOn ()) + { + if (extendedFormats_) + JDTrace.logInformation (this, "Using extended datastreams"); + else + JDTrace.logInformation (this, "Using original datastreams"); + } + + // Send an RDB name to the system only if connecting to + // v5r2 and newer versions of IBM i + if (vrm_ >= JDUtilities.vrm520) // @J2a + { + // @J2a + StringBuffer RDBName = new StringBuffer(properties_.getString (JDProperties.DATABASE_NAME)); // @J2a + if (RDBName.length() > 0) // @J2a + { + // @J2a + RDBName.append(" "); // @J2a + RDBName.setLength(18); // @J2a + request.setRDBName(RDBName.toString().toUpperCase(), tempConverter); // @J2a + if (JDTrace.isTraceOn ()) // @J2a + JDTrace.logInformation (this, "RDB Name = -->" + RDBName + "<--"); // @J2a + } // @J2a + } // @J2a + + //@PDA 550 client interface info settings + //These three settings cannot be updated by user apps. + //This gives driver information to host server for any logging or future diagnostics. + if (vrm_ >= JDUtilities.vrm610) + { + //these strings are not mri translated for future diagnostic tools, searching etc on host server + request.setInterfaceType( "JDBC", tempConverter); + request.setInterfaceName( "IBM Toolbox for Java", tempConverter); + request.setInterfaceLevel( AS400JDBCDriver.DRIVER_LEVEL_, tempConverter); + + //@DFA 550 decfloat rounding mode + short roundingMode = 0; //@DFA + String roundingModeStr = properties_.getString(JDProperties.DECFLOAT_ROUNDING_MODE); //@DFA + if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_EVEN)) //@DFA + roundingMode = 0; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_UP)) //@DFA + roundingMode = 6; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_DOWN)) //@DFA + roundingMode = 2; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_CEILING)) //@DFA + roundingMode = 3; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_FLOOR)) //@DFA + roundingMode = 4; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_UP)) //@DFA + roundingMode = 1; //@DFA + else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_DOWN)) //@DFA + roundingMode = 5; //@DFA + + //only need to send request if not default 0 (half even) + if(roundingMode != 0) //@DFA + request.setDecfloatRoundingMode(roundingMode); //@DFA + + //@eof Close on EOF + request.setCloseEOF( 0xE8) ; + + } + + //@710 + if (vrm_ >= JDUtilities.vrm710) + { + int car = properties_.getInt(JDProperties.CONCURRENT_ACCESS_RESOLUTION); //@cc1 + if( !(properties_.getString(JDProperties.CONCURRENT_ACCESS_RESOLUTION)).equals( JDProperties.CONCURRENTACCESS_NOT_SET )) //@cc1 + { //@cc1 + request.setConcurrentAccessResolution( car ); //@cc1 + //Use instance variable to to "current setting". + //This will allow the Connection setting to override DataSource + //setting for future updates to this property from the Connection object. //@cc1 + concurrentAccessResolution_ = car; //@cc1 + } //@cc1 + } + + // Send the request and process the reply. + reply = sendAndReceive (request); + + int errorClass = reply.getErrorClass(); + int returnCode = reply.getReturnCode(); + + // Sort sequence attribute cannot be set. + if ((errorClass == 7) + && ((returnCode == 301) || (returnCode == 303))) + postWarning (JDError.getSQLWarning (this, id_, errorClass, returnCode)); + + // Language feature code id was not changed. This is caused + // when the secondary language can not be added to the library + // list, and shows up as a PWS0003. + else if ((errorClass == 7) && (returnCode == 304)) + postWarning (JDError.getSQLWarning (this, id_, errorClass, returnCode)); + + // -704 is RDB (IASP) does not exist. We do not go back to the system to get + // error info since they are sending an invalid attribute exception when the + // IASP is not found. We can create a better error than that. + else if ((errorClass == 7) && (returnCode == -704)) // @J2a + { // @J2a + try // @J2a + { // @J2a + close(); // @J2a + } // @J2a + catch (Exception e) {} // eat errors on close // @J2a + JDError.throwSQLException(this, JDError.EXC_RDB_DOES_NOT_EXIST); // @J2a + } // @J2a + + // Other system errors. + else if (errorClass != 0) + JDError.throwSQLException (this, this, id_, errorClass, returnCode); + + // Process the returned server attributes. + serverAttributes = reply.getServerAttributes (); + } + finally + { + if (request != null) { + request.returnToPool(); request = null; + } + // We cannot return the reply to the pool while it is still being used in the serverAttributes structure + // if (reply != null) reply.returnToPool(); + } + + // The CCSID that comes back is a mixed CCSID (i.e. mixed + // SBCS and DBCS). This will be the CCSID that all + // non-graphic data will be returned as for this + // connection, so we own the converter here. + int serverCCSID = serverAttributes.getServerCCSID(); + //@P0D converter_ = ConverterImplRemote.getConverter (serverCCSID, as400_); + converter_ = ConvTable.getTable(serverCCSID, null); //@P0A + + // Get the server functional level. It comes back as in the @E7A + // format VxRxMx9999. @E7A + String serverFunctionalLevelAsString = serverAttributes.getServerFunctionalLevel(converter_); // @E7A + try + { // @E7A + serverFunctionalLevel_ = Integer.parseInt(serverFunctionalLevelAsString.substring(6)); // @E7A + } // @E7A + catch (NumberFormatException e) + { // @E7A + serverFunctionalLevel_ = 0; // @E7A + } // @E7A + + // Get the job number, but only if . @E8A + if (serverFunctionalLevel_ >= 5) // @E8A + serverJobIdentifier_ = serverAttributes.getServerJobIdentifier(converter_); // @E8A + + // User no longer needs to specify "for update" on their SQL + // statements if running to v5r1 with a PTF. (V5R2 and later + // is handled in another piece of code) + if ((vrm_ == JDUtilities.vrm510) && //@J31a + ( serverFunctionalLevel_ >= 10)) //@J31a + mustSpecifyForUpdate_ = false; //@J31a + + if (JDTrace.isTraceOn ()) + { // @C2C + int v = (vrm_ & 0xffff0000) >>> 16; // @D1A + int r = (vrm_ & 0x0000ff00) >>> 8; // @D1A + int m = (vrm_ & 0x000000ff); // @D1A + JDTrace.logInformation (this, "JDBC driver major version = " // @C2A + + AS400JDBCDriver.MAJOR_VERSION_); // @C2A + //Check version - V5R2 and earlier run on OS/400, V5R3 and later run on IBM i + if(((v==5) && (r>=3)) || (v>5)) + JDTrace.logInformation(this, "IBM i VRM = V" + v + + "R" + r + "M" + m); + else + JDTrace.logInformation (this, "OS/400 VRM = V" + v // @C2A + + "R" + r + "M" + m); // @C2A + JDTrace.logInformation (this, "Server CCSID = " + serverCCSID); + JDTrace.logInformation(this, "Server functional level = " // @E7A + + serverFunctionalLevelAsString // @E7A + + " (" + serverFunctionalLevel_ + ")"); // @E7A + + StringBuffer buffer = new StringBuffer(); // @E8A + if (serverJobIdentifier_ == null) // @E8A + buffer.append("Not available"); // @E8A + else + { // @E8A + buffer.append(serverJobIdentifier_.substring(20, 26).trim()); // job number // @E8A + buffer.append('/'); // @E8A + buffer.append(serverJobIdentifier_.substring(10, 20).trim()); // user name // @E8A + buffer.append('/'); // @E8A + buffer.append(serverJobIdentifier_.substring(0, 10).trim()); // job name // @E8A + } // @E8A + JDTrace.logInformation(this, "Server job identifier = " + buffer); // @E8A + } // @C2A + + // @E2D // Wait to load graphic converter until it is needed. + // @E2D graphicConverter_ = null; + // @E2D graphicConverterLoaded_ = false; + + // Get the catalog name from the RDB entry. If no RDB entry is + // set on the system, then use the system name from the AS400 object + // (which originally came from the URL). + String rdbEntry = serverAttributes.getRelationalDBName (converter_).trim(); + if ((rdbEntry.length() > 0) && (! rdbEntry.equalsIgnoreCase ("*N"))) + catalog_ = rdbEntry; + + // In the cases where defaults come from the server + // job, get the defaults for properties that were not set. + if (decimalSeparator == -1) + { + switch (serverAttributes.getDecimalSeparatorPO ()) + { + case 0: + properties_.setString (JDProperties.DECIMAL_SEPARATOR, JDProperties.DECIMAL_SEPARATOR_PERIOD); + break; + case 1: + properties_.setString (JDProperties.DECIMAL_SEPARATOR, JDProperties.DECIMAL_SEPARATOR_COMMA); + break; + } + } + + if (dateFormat == -1) + { + switch (serverAttributes.getDateFormatPO ()) + { + case 0: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_JULIAN); + break; + case 1: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_MDY); + break; + case 2: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_DMY); + break; + case 3: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_YMD); + break; + case 4: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_USA); + break; + case 5: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_ISO); + break; + case 6: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_EUR); + break; + case 7: + properties_.setString (JDProperties.DATE_FORMAT, JDProperties.DATE_FORMAT_JIS); + break; + } + } + + if (dateSeparator == -1) + { + switch (serverAttributes.getDateSeparatorPO ()) + { + case 0: + properties_.setString (JDProperties.DATE_SEPARATOR, JDProperties.DATE_SEPARATOR_SLASH); + break; + case 1: + properties_.setString (JDProperties.DATE_SEPARATOR, JDProperties.DATE_SEPARATOR_DASH); + break; + case 2: + properties_.setString (JDProperties.DATE_SEPARATOR, JDProperties.DATE_SEPARATOR_PERIOD); + break; + case 3: + properties_.setString (JDProperties.DATE_SEPARATOR, JDProperties.DATE_SEPARATOR_COMMA); + break; + case 4: + properties_.setString (JDProperties.DATE_SEPARATOR, JDProperties.DATE_SEPARATOR_SPACE); + break; + } + } + + if (timeFormat == -1) + { + switch (serverAttributes.getTimeFormatPO ()) + { + case 0: + properties_.setString (JDProperties.TIME_FORMAT, JDProperties.TIME_FORMAT_HMS); + break; + case 1: + properties_.setString (JDProperties.TIME_FORMAT, JDProperties.TIME_FORMAT_USA); + break; + case 2: + properties_.setString (JDProperties.TIME_FORMAT, JDProperties.TIME_FORMAT_ISO); + break; + case 3: + properties_.setString (JDProperties.TIME_FORMAT, JDProperties.TIME_FORMAT_EUR); + break; + case 4: + properties_.setString (JDProperties.TIME_FORMAT, JDProperties.TIME_FORMAT_JIS); + break; + } + } + + if (timeSeparator == -1) + { + switch (serverAttributes.getTimeSeparatorPO ()) + { + case 0: + properties_.setString (JDProperties.TIME_SEPARATOR, JDProperties.TIME_SEPARATOR_COLON); + break; + case 1: + properties_.setString (JDProperties.TIME_SEPARATOR, JDProperties.TIME_SEPARATOR_PERIOD); + break; + case 2: + properties_.setString (JDProperties.TIME_SEPARATOR, JDProperties.TIME_SEPARATOR_COMMA); + break; + case 3: + properties_.setString (JDProperties.TIME_SEPARATOR, JDProperties.TIME_SEPARATOR_SPACE); + break; + } + } + } + catch (DBDataStreamException e) + { + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + // @J5D catch (IOException e) { + catch (UnsupportedEncodingException e) + { // @J5C + JDError.throwSQLException (this, JDError.EXC_INTERNAL, e); + } + finally + { + // Don't return the reply to the pool until the very end, + // as it is used by the DBReplyServerAttributes object + if (reply != null) { reply.returnToPool(); reply = null; } + } + } + + + + //@A3A + // Implementation note: Don't use this object internally because we could be running in a proxy environment + // The purpose of this method is to simply hold the full AS400 object so it can be retrieved from the Connection + void setSystem (AS400 as400) + throws SQLException // @EGA + { + as400PublicClassObj_ = as400; + } + + + + // @D2C + /** + Sets the transaction isolation level. The transaction + isolation level cannot be changed while in the middle of + a transaction. + +

JDBC and DB2 for IBM i use different terminology for transaction + isolation levels. The following table provides a terminology + mapping: + +

+ + + + + +
IBM i isolation levelJDBC transaction isolation level
*CHG TRANSACTION_READ_UNCOMMITTED
*CS TRANSACTION_READ_COMMITTED
*ALL TRANSACTION_READ_REPEATABLE_READ
*RR TRANSACTION_SERIALIZABLE
+ + @param level The transaction isolation level. Possible + values are: +

+ + @exception SQLException If the connection is not open, + the input level is not valid + or unsupported, or a transaction + is active. + **/ + public void setTransactionIsolation (int level) + throws SQLException + { + checkOpen (); + + transactionManager_.setIsolation (level); + + if (JDTrace.isTraceOn()) + JDTrace.logProperty (this, "Transaction isolation", transactionManager_.getIsolation ()); + } + + + + // JDBC 2.0 + /** + Sets the type map to be used for distinct and structured + types. + +

Note: Distinct types are supported by DB2 for IBM i, but + are not externalized by the IBM Toolbox for Java JDBC driver. + In other words, distinct types behave as if they are the underlying + type. Structured types are not supported by DB2 for IBM i. + Consequently, this driver does not support the type map. + + @param typeMap The type map. + + @exception SQLException This exception is always thrown. + **/ + public void setTypeMap (Map typeMap) + throws SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + } + + + + /** + Returns the connection's catalog name. This is the + name of the IBM i system. + + @return The catalog name. + **/ + public String toString () + { + return catalog_; + } + + + + /** + Indicates if the connection is using extended formats. + + @return true if the connection is using extended formats, false + otherwise. + **/ + boolean useExtendedFormats () + throws SQLException // @EGA + { + return extendedFormats_; + } + + + //@pda jdbc40 + protected String[] getValidWrappedList() + { + return new String[] { "com.ibm.as400.access.AS400JDBCConnection", "java.sql.Connection" }; + } + + + + //@PDA jdbc40 + /** + * Returns true if the connection has not been closed and is still valid. + * The driver shall submit a query on the connection or use some other + * mechanism that positively verifies the connection is still valid when + * this method is called. + *

+ * The query submitted by the driver to validate the connection shall be + * executed in the context of the current transaction. + * + * @param timeout - The time in seconds to wait for the database operation + * used to validate the connection to complete. If + * the timeout period expires before the operation + * completes, this method returns false. A value of + * 0 indicates a timeout is not applied to the + * database operation. + *

+ * @return true if the connection is valid, false otherwise + * @exception SQLException if a database access error occurs. + */ +/* ifdef JDBC40 */ + public boolean isValid(int timeout) throws SQLException + { + DBSQLRequestDS request = null; + DBReplyRequestedDS reply = null; + int errorClass = 0; + int returnCode = 0; + ReentrantLock lock = new ReentrantLock(); + + // Return exception if timeout is less than 0.. @D6A + if (timeout < 0) { + JDError.throwSQLException( this, JDError.EXC_ATTRIBUTE_VALUE_INVALID); + } + + try + { + // inner class to run timer in sep thread + class CommTimer implements Runnable + { + + Thread otherThread; + ReentrantLock lock; + int timeout; + + public void run() + { + try + { + Thread.sleep(timeout * 1000); + lock.lockInterruptibly(); //lock, so only one thread can call interrupt + otherThread.interrupt(); + lock.unlock(); + + }catch(InterruptedException ie) + { + //interrupted from notifyThread because request/reply is done. just return from run() + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Connection.isValid timer interrupted and stopped"); + } + + } + + public CommTimer(Thread otherThread, int timeout, ReentrantLock lock ) + { + this.otherThread = otherThread; + this.timeout = timeout; + this.lock = lock; + } + }; + + CommTimer timer = null; + Thread t = null; + + // Only use timeout if > 0. @D6A + if (timeout > 0) { + timer = new CommTimer( Thread.currentThread(), timeout, lock); //pass in ref to main thread so timer can interrupt if blocked on IO + t = new Thread(timer); + t.start(); //sleeps for timeout and then interrupts main thread if it is still blocked on IO + } + + try + { + request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_TEST_CONNECTION, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0); + reply = sendAndReceive(request); + + lock.lockInterruptibly(); //lock, so only one thread can call interrupt + if (t != null) t.interrupt(); //stop timer thread @D6C + lock.unlock(); + errorClass = reply.getErrorClass(); + returnCode = reply.getReturnCode(); + + } catch(Exception ex) { + try { + // Make sure timeout thread is stopped @D6A + lock.lockInterruptibly(); //lock, so only one thread can call interrupt + if (t != null) t.interrupt(); //stop timer thread + lock.unlock(); + } catch (Exception ex2) { + } + //interruptedException is wrapped in sqlException + //if exception occurs, just return false since connection is not valid + //this happens if timer ends before sendAndReceive returns + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Connection.isValid timed out or could not verify valid connection"); + return false; + } + + if(errorClass == 7 && returnCode == -201) + return true; + else + return false; + + } + catch(Exception e) + { + //implmentation note: if any exception happens, just return false, since conn is not valid + return false; + } + finally + { + if (request != null) { + request.returnToPool(); request = null; + } + if (reply != null) { + reply.returnToPool(); reply = null; // commented out code + } + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Connection.isValid call complete"); + } + + } + +/* endif */ + + + + //@PDA 550 client info + /** + * Sets the value of the client info property specified by name to the + * value specified by value. + *

+ * Applications may use the DatabaseMetaData.getClientInfoProperties + * method to determine the client info properties supported by the driver + * and the maximum length that may be specified for each property. + *

+ * The driver stores the value specified in a suitable location in the + * database. For example in a special register, session parameter, or + * system table column. For efficiency the driver may defer setting the + * value in the database until the next time a statement is executed or + * prepared. Other than storing the client information in the appropriate + * place in the database, these methods shall not alter the behavior of + * the connection in anyway. The values supplied to these methods are + * used for accounting, diagnostics and debugging purposes only. + *

+ * The driver shall generate a warning if the client info name specified + * is not recognized by the driver. + *

+ * If the value specified to this method is greater than the maximum + * length for the property the driver may either truncate the value and + * generate a warning or generate a SQLException. If the driver + * generates a SQLException, the value specified was not set on the + * connection. + *

+ * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @param name The name of the client info property to set + * @param value The value to set the client info property to. If the + * value is null, the current value of the specified + * property is cleared. + *

+ * @throws SQLClientInfoException if the database returns an error while + * setting the client info value on the database server. + *

+ */ + public void setClientInfo(String name, String value) +/* ifdef JDBC40 */ + throws SQLClientInfoException +/* endif */ +/* ifndef JDBC40 + throws SQLException + endif */ + { + + DBSQLAttributesDS request = null; + DBReplyRequestedDS setClientInfoReply = null; + ConvTable tempConverter = null; + + String oldValue = null; //save in case we get error from host db + + // in order to reset if null value is passed in, use empty string + if (value == null) + value = ""; + + try + { + if (getVRM() >= JDUtilities.vrm610) + { + request = DBDSPool.getDBSQLAttributesDS(DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); + tempConverter = ConvTable.getTable(as400_.getCcsid(), null); + + + } + + if (name.equals(applicationNamePropertyName_)) + { + oldValue = applicationName_; + applicationName_ = value; + if (request != null ) + request.setClientInfoApplicationName(value, tempConverter); + + } else if (name.equals(clientUserPropertyName_)) + { + oldValue = clientUser_; + clientUser_ = value; + if (request != null ) + request.setClientInfoClientUser(value, tempConverter); + + } else if (name.equals(clientAccountingPropertyName_)) + { + oldValue = clientAccounting_; + clientAccounting_ = value; + if (request != null ) + request.setClientInfoClientAccounting(value, tempConverter); + + } else if (name.equals(clientHostnamePropertyName_)) + { + oldValue = clientHostname_; + clientHostname_ = value; + if (request != null) + request.setClientInfoClientHostname(value, tempConverter); + + } else if (name.equals(clientProgramIDPropertyName_)) //@PDA add block for ProgramID + { + oldValue = clientProgramID_; + clientProgramID_ = value; + if (request != null) + request.setClientInfoProgramID(value, tempConverter); + + } else + { + oldValue = null; + // post generic syntax error for invalid clientInfo name + postWarning(JDError.getSQLWarning(JDError.EXC_SYNTAX_ERROR)); + } + + if ((getVRM() >= JDUtilities.vrm610) && (oldValue != null)) + { + setClientInfoReply = sendAndReceive(request); + int errorClass = setClientInfoReply.getErrorClass(); + //throw SQLException + if (errorClass != 0) + JDError.throwSQLException(this, id_, errorClass, setClientInfoReply.getReturnCode()); + + } + } catch (Exception e) + { + //reset old value + if (name.equals(applicationNamePropertyName_)) + applicationName_ = oldValue; + else if (name.equals(clientUserPropertyName_)) + clientUser_ = oldValue; + else if (name.equals(clientAccountingPropertyName_)) + clientAccounting_ = oldValue; + else if (name.equals(clientHostnamePropertyName_)) + clientHostname_ = oldValue; + else if (name.equals(clientProgramIDPropertyName_)) //@pda + clientProgramID_ = oldValue; +/* ifdef JDBC40 */ + + //@PDD jdbc40 merge HashMap m = new HashMap(); + HashMap m = new HashMap(); + m.put(name, ClientInfoStatus.REASON_UNKNOWN); + JDError.throwSQLClientInfoException( this, JDError.EXC_INTERNAL, e, m ); + +/* endif */ +/* ifndef JDBC40 + JDError.throwSQLException( this, JDError.EXC_INTERNAL, e); + endif */ + } finally + { + if (request != null) { + request.returnToPool(); request = null; + } + if (setClientInfoReply != null) { + setClientInfoReply.returnToPool(); setClientInfoReply = null; // only error class used + } + } + } + + //@PDA 550 client info + /** + * Sets the value of the connection's client info properties. The + * Properties object contains the names and values of the + * client info properties to be set. The set of client info properties + * contained in the properties list replaces the current set of client info + * properties on the connection. If a property that is currently set on the + * connection is not present in the properties list, that property is + * cleared. Specifying an empty properties list will clear all of the + * properties on the connection. See + * setClientInfo (String, String) for more information. + *

+ * If an error occurs in setting any of the client info properties, a + * ClientInfoException is thrown. The + * ClientInfoException contains information indicating which + * client info properties were not set. The state of the client information + * is unknown because some databases do not allow multiple client info + * properties to be set atomically. For those databases, one or more + * properties may have been set before the error occurred. + *

+ * + * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * + * @param properties + * the list of client info properties to set + *

+ * @throws SQLClientInfoException + * if the database returns an error while setting the + * clientInfo values on the database + *

+ */ + public void setClientInfo(Properties properties) +/* ifdef JDBC40 */ + throws SQLClientInfoException +/* endif */ +/* ifndef JDBC40 + throws SQLException + endif */ + { + String newApplicationName = properties.getProperty(applicationNamePropertyName_); + String newClientHostname = properties.getProperty(clientHostnamePropertyName_); + String newClientUser = properties.getProperty(clientUserPropertyName_); + String newClientAccounting = properties.getProperty(clientAccountingPropertyName_); + String newClientProgramID = properties.getProperty(clientProgramIDPropertyName_); //@pda + + //In order to reset if null value is passed in, use empty string + //per javadoc, clear its value if not specified in properties + if (newApplicationName == null) + newApplicationName = ""; + if (newClientHostname == null) + newClientHostname = ""; + if (newClientUser == null) + newClientUser = ""; + if (newClientAccounting == null) + newClientAccounting = ""; + if (newClientProgramID == null) //@PDA + newClientProgramID = ""; + + DBSQLAttributesDS request = null; + DBReplyRequestedDS setClientInfoReply = null; + ConvTable tempConverter = null; + try + { + if (getVRM() >= JDUtilities.vrm610) + { + request = DBDSPool.getDBSQLAttributesDS(DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); + tempConverter = ConvTable.getTable(as400_.getCcsid(), null); + + request.setClientInfoApplicationName(newApplicationName, tempConverter); + + request.setClientInfoClientUser(newClientUser, tempConverter); + + request.setClientInfoClientAccounting(newClientAccounting, tempConverter); + + request.setClientInfoClientHostname(newClientHostname, tempConverter); + + request.setClientInfoProgramID(newClientProgramID, tempConverter); //@pda + + setClientInfoReply = sendAndReceive(request); + int errorClass = setClientInfoReply.getErrorClass(); + if (errorClass != 0) + JDError.throwSQLException(this, id_, errorClass, setClientInfoReply.getReturnCode()); + } + + //update local values after request/reply in case of exception + applicationName_ = newApplicationName; + clientHostname_ = newClientHostname; + clientUser_ = newClientUser; + clientAccounting_ = newClientAccounting; + clientProgramID_ = newClientProgramID; + + } catch( Exception e) + { +/* ifdef JDBC40 */ + //create Map for exception constructor + //@PDD jdbc40 merge HashMap m = new HashMap(); + HashMap m = new HashMap(); + Enumeration clientInfoNames = properties.keys(); + while( clientInfoNames.hasMoreElements()) + { + String clientInfoName = (String)clientInfoNames.nextElement(); + m.put(clientInfoName, ClientInfoStatus.REASON_UNKNOWN); + } + JDError.throwSQLClientInfoException( this, JDError.EXC_INTERNAL, e, m); + +/* endif */ +/* ifndef JDBC40 + JDError.throwSQLException( this, JDError.EXC_INTERNAL, e); + endif */ + } finally + { + if (request != null) { + request.returnToPool(); request = null; + } + if (setClientInfoReply != null) { + setClientInfoReply.returnToPool(); setClientInfoReply=null; // only error class used + } + } + + } + + //@PDA 550 client info + /** + * Returns the value of the client info property specified by name. This + * method may return null if the specified client info property has not + * been set and does not have a default value. This method will also + * return null if the specified client info property name is not supported + * by the driver. + *

+ * Applications may use the DatabaseMetaData.getClientInfoProperties + * method to determine the client info properties supported by the driver. + *

+ * + * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @param name The name of the client info property to retrieve + *

+ * @return The value of the client info property specified + *

+ * @throws SQLException if the database returns an error when + * fetching the client info value from the database. + *

+ * see java.sql.DatabaseMetaData#getClientInfoProperties + */ + public String getClientInfo(String name) throws SQLException + { + if (name.equals(applicationNamePropertyName_)) + return applicationName_; + else if (name.equals(clientUserPropertyName_)) + return clientUser_; + else if (name.equals(clientAccountingPropertyName_)) + return clientAccounting_; + else if (name.equals(clientHostnamePropertyName_)) + return clientHostname_; + else if (name.equals(clientProgramIDPropertyName_)) //@pda + return clientProgramID_; + else + { + //post generic syntax error for invalid clientInfo name + //since javadoc for setClientInfo(String,String) says to generate warning, we will do same here and return null + postWarning(JDError.getSQLWarning(JDError.EXC_SYNTAX_ERROR)); + return null; + } + } + + //@PDA 550 client info + /** + * Returns a list containing the name and current value of each client info + * property supported by the driver. The value of a client info property + * may be null if the property has not been set and does not have a + * default value. + *

+ * + * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @return A Properties object that contains the name and current value of + * each of the client info properties supported by the driver. + *

+ * @throws SQLException if the database returns an error when + * fetching the client info values from the database + */ + public Properties getClientInfo() throws SQLException + { + Properties props = new Properties(); + props.setProperty(applicationNamePropertyName_, applicationName_); + props.setProperty(clientAccountingPropertyName_, clientAccounting_); + props.setProperty(clientHostnamePropertyName_, clientHostname_); + props.setProperty(clientUserPropertyName_, clientUser_); + props.setProperty(clientProgramIDPropertyName_, clientProgramID_); //@pda + return props; + } + + + + + + //@PDA jdbc40 + /** + * Constructs an object that implements the Clob interface. The object + * returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of + * the Clob interface may be used to add data to the Clob. + * @return An object that implements the Clob interface + * @throws SQLException if an object that implements the + * Clob interface can not be constructed. + * + */ + public Clob createClob() throws SQLException + { + return new AS400JDBCClob("", AS400JDBCClob.MAX_LOB_SIZE); + } + + //@PDA jdbc40 + /** + * Constructs an object that implements the Blob interface. The object + * returned initially contains no data. The setBinaryStream and + * setBytes methods of the Blob interface may be used to add data to + * the Blob. + * @return An object that implements the Blob interface + * @throws SQLException if an object that implements the + * Blob interface can not be constructed + * + */ + public Blob createBlob() throws SQLException + { + return new AS400JDBCBlob(new byte[0], AS400JDBCBlob.MAX_LOB_SIZE); //@pdc 0 len array + } + + //@PDA jdbc40 + /** + * Constructs an object that implements the NClob interface. The object + * returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of the NClob interface may + * be used to add data to the NClob. + * @return An object that implements the NClob interface + * @throws SQLException if an object that implements the + * NClob interface can not be constructed. + * + */ +/* ifdef JDBC40 */ + public NClob createNClob() throws SQLException + { + return new AS400JDBCNClob("", AS400JDBCNClob.MAX_LOB_SIZE); + } +/* endif */ + + //@PDA jdbc40 + /** + * Constructs an object that implements the SQLXML interface. The object + * returned initially contains no data. The createXMLStreamWriter object and + * setString method of the SQLXML interface may be used to add data to the SQLXML + * object. + * @return An object that implements the SQLXML interface + * @throws SQLException if an object that implements the SQLXML interface can not + * be constructed + */ +/* ifdef JDBC40 */ + public SQLXML createSQLXML() throws SQLException + { + return new AS400JDBCSQLXML(AS400JDBCSQLXML.MAX_XML_SIZE); + } +/* endif */ + + //@PDA //@array + /** + * Factory method for creating Array objects. + * + * @param typeName the SQL name of the type the elements of the array map to. The typeName is a + * database-specific name which may be the name of a built-in type, a user-defined type or a standard SQL type supported by this database. This + * is the value returned by Array.getBaseTypeName + * For Toolbox, the typeName will correspond to a typename in java.sql.Types. + * + * @param elements the elements that populate the returned object + * @return an Array object whose elements map to the specified SQL type + * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + */ + public Array createArrayOf(String typeName, Object[] elements) throws SQLException + { + //@array + return new AS400JDBCArray(typeName, elements, this.vrm_, this); + } + + //@PDA jdbc40 + /** + * Factory method for creating Struct objects. + * + * @param typeName the SQL type name of the SQL structured type that this Struct + * object maps to. The typeName is the name of a user-defined type that + * has been defined for this database. It is the value returned by + * Struct.getSQLTypeName. + * @param attributes the attributes that populate the returned object + * @return a Struct object that maps to the given SQL type and is populated with the given attributes + * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + */ + public Struct createStruct(String typeName, Object[] attributes) throws SQLException + { + JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + return null; + } + + + //@2KRA + /** + * Starts or stops the Database Host Server trace for this connection. + * Note: This method is only supported when running to IBM i V5R3 or later + * and is ignored if you specified to turn on database host server tracing + * using the 'server trace' connection property. + * @param trace true to start database host server tracing, false to end it. + */ + public void setDBHostServerTrace(boolean trace){ + try{ + if(getVRM() >= JDUtilities.vrm530){ + // See if tracing was specified by server trace property + // Server Job Trace + boolean traceServerJob = ((traceServer_ & ServerTrace.JDBC_TRACE_SERVER_JOB) > 0); + // Database Host Server Trace + boolean traceDatabaseHostServer = (((traceServer_ & ServerTrace.JDBC_TRACE_DATABASE_HOST_SERVER) > 0)); + String serverJobIdentifier = getServerJobIdentifier(); + boolean SQLNaming = properties_.getString(JDProperties.NAMING).equals(JDProperties.NAMING_SQL); + + if(!traceDatabaseHostServer){ // database host server trace was not already started + if(trace) // user requested tracing be turned on + { + try{ + if(getVRM() == JDUtilities.vrm530){ // run command for V5R3 + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*TRCTYPE) " + + "TRCTYPE((TESTA *INFO))", SQLNaming); + } + else{ // run command for V5R4 and higher + JDUtilities.runCommand(this, "QSYS/STRTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") JOB(*) MAXSTG(128000) JOBTRCTYPE(*TRCTYPE) " + + "TRCTYPE((*DBHSVR *INFO))", SQLNaming); + } + databaseHostServerTrace_ = true; + }catch(Exception e){ + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to start database host server tracing failed, could not trace server job"); + } + } + else // user requested tracing be turned off + { + // Only issue ENDTRC if not already done. + if(!traceServerJob) // turn off it we don't have to wait to turn off server job tracing + { + try{ + JDUtilities.runCommand(this, "QSYS/ENDTRC SSNID(QJT" + + serverJobIdentifier.substring(20) + + ") DTAOPT(*LIB) DTALIB(QUSRSYS) RPLDTA(*YES) PRTTRC(*YES)", SQLNaming ); + + JDUtilities.runCommand(this, "QSYS/DLTTRC DTAMBR(QJT" + + serverJobIdentifier.substring(20) + + ") DTALIB(QUSRSYS)", SQLNaming ); + databaseHostServerTrace_ = false; + } + catch(Exception e){ + JDTrace.logDataEvenIfTracingIsOff(this, "Attempt to end database host server tracing failed."); + } + } + } + } + } + }catch(SQLException e){ + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Attempt to start/stop database host server tracing failed."); + } + + } + + + //@A2A + public boolean doUpdateDeleteBlocking() { + return doUpdateDeleteBlocking_; + } + + // @A6A + public int getMaximumBlockedInputRows() { + return maximumBlockedInputRows_; + } + + /** + * Terminates an open connection. Calling abort results in: + *

+ *

+ * Calling abort marks the connection closed and releases any resources. + * Calling abort on a closed connection is a no-op. + *

It is possible that the aborting and releasing of the resources that are + * held by the connection can take an extended period of time. + * When the abort method returns, the connection will have been marked as closed + * and the Executor that was passed as a parameter to abort may still be executing + * tasks to release resources. + *

+ * This method checks to see that there is an SQLPermission object before + * allowing the method to proceed. If a SecurityManager exists and its + * checkPermission method denies calling abort, this method throws a + * java.lang.SecurityException. + * @param executor The Executor implementation which will be used by abort. + * @throws SQLException - if a database access error occurs or the executor is null + * @throws SecurityException - if a security manager exists and its checkPermission + * method denies calling abort + */ +/* ifdef JDBC40 */ + public void abort(Executor executor) throws SQLException { + + // Check for null executor + if (executor == null) { + JDError.throwSQLException(JDError.EXC_PARAMETER_TYPE_INVALID); + } + + // Check for authority + SecurityManager security = System.getSecurityManager(); + if (security != null) { + SQLPermission sqlPermission = new SQLPermission("callAbort"); + security.checkPermission(sqlPermission); + } + + // Calling on a close connection is a no-op + if (aborted_ || (server_ == null)) { + return; + } + + // + // Mark the connection as aborted. Any call to closed will see that it is closed. + // + aborted_ = true; + + // + // Prepare and start the executor to clean everything up. + // + Runnable runnable = new AS400JDBCConnectionAbortRunnable(this); + + executor.execute(runnable); + } +/* endif */ + + + + /** + * Retrieves this Connection object's current schema name. + * @return the current schema name or null if there is none + * @throws SQLException if a database access error occurs or this method is called on a closed connection + */ + public String getSchema() throws SQLException { + + + Statement s = createStatement(); + String query; + boolean SQLNaming = properties_.getString(JDProperties.NAMING).equals(JDProperties.NAMING_SQL); + if (SQLNaming) { + query = "SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1"; + } else { + query = "SELECT CURRENT SCHEMA FROM SYSIBM/SYSDUMMY1"; + } + + ResultSet rs = s.executeQuery(query); + rs.next(); + String schema = rs.getString(1); + rs.close(); + s.close(); + return schema; + } + + /** + * Sets the maximum period a Connection or objects created from the Connection will wait for the database to + * reply to any one request. If any request remains unanswered, the waiting method will return with a + * SQLException, and the Connection or objects created from the Connection will be marked as closed. + * Any subsequent use of the objects, with the exception of the close, isClosed or Connection.isValid methods, + * will result in a SQLException. + * + *

In the JTOpen JDBC driver, this is implemented by setting the SoTimeout of the underlying socket. + *

Currently, setting the network timeout is only supported when the "thread used" property is false. + *

When the driver determines that the setNetworkTimeout timeout value has expired, the JDBC driver marks + * the connection closed and releases any resources held by the connection. + *

This method checks to see that there is an SQLPermission object before allowing the method to proceed. + * If a SecurityManager exists and its checkPermission method denies calling setNetworkTimeout, this method + * throws a java.lang.SecurityException. + *@param timeout - The time in milliseconds to wait for the database operation to complete. If the + * JDBC driver does not support milliseconds, the JDBC driver will round the value up to the nearest second. + * If the timeout period expires before the operation completes, a SQLException will be thrown. A value of + * 0 indicates that there is not timeout for database operations. + * @throws SQLException + * @throws SQLException - if a database access error occurs, this method is called on a closed connection, + * or the value specified for seconds is less than 0. + * @throws SecurityException - if a security manager exists and its checkPermission method denies calling + * setNetworkTimeout. + * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method + * @see SecurityManager.checkPermission(java.security.Permission), Statement.setQueryTimeout(int), + * getNetworkTimeout(), abort(java.util.concurrent.Executor), Executor + */ + + public void setNetworkTimeout(int timeout) throws SQLException { + +/* ifdef JDBC40 */ + + SecurityManager security = System.getSecurityManager(); + if (security != null) { + SQLPermission sqlPermission = new SQLPermission("setNetworkTimeout"); + security.checkPermission(sqlPermission); + } +/* endif */ + + + // Make sure that the THREAD_USED property is false. The default is true + String threadUsedProperty = properties_.getString(JDProperties.THREAD_USED); + + if (threadUsedProperty == null) { + if (timeout > 0 ) { + JDError.throwSQLException(JDError.EXC_FUNCTION_NOT_SUPPORTED); + } + } else { + if (threadUsedProperty.equalsIgnoreCase("true")) { + if (timeout > 0 ) { + JDError.throwSQLException(JDError.EXC_FUNCTION_NOT_SUPPORTED); + } + } + } + + + // Make sure value is not negative + if (timeout < 0) { + JDError.throwSQLException(JDError.EXC_PARAMETER_TYPE_INVALID); + } + + // Calling on a closed connection is a no-op + checkOpen (); + + try { + server_.setSoTimeout(timeout); + } catch (SocketException e) { + JDError.throwSQLException(JDError.EXC_COMMUNICATION_LINK_FAILURE, e); + } + } + + /** + * Retrieves the number of milliseconds the driver will wait for a database request to complete. If the limit is exceeded, a SQLException is thrown. + * @return The current timeout limit in milliseconds; zero means there is no limit + * @throws SQLException - if a database access error occurs or this method is called on a closed Connection + * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method + * @since JTOpen 7.X + * @see #setNetworkTimeout(java.util.concurrent.Executor, int) + */ + public int getNetworkTimeout() throws SQLException { + checkOpen (); + + try { + return server_.getSoTimeout(); + } catch (SocketException e) { + JDError.throwSQLException(JDError.EXC_COMMUNICATION_LINK_FAILURE, e); + return 0; + } + } + + /** + * Sets the maximum period a Connection or objects created from the Connection will wait for the database to + * reply to any one request. If any request remains unanswered, the waiting method will return with a + * SQLException, and the Connection or objects created from the Connection will be marked as closed. + * Any subsequent use of the objects, with the exception of the close, isClosed or Connection.isValid methods, + * will result in a SQLException. + *

Note: This method is intended to address a rare but serious condition where network partitions can + * cause threads issuing JDBC calls to hang uninterruptedly in socket reads, until the OS TCP-TIMEOUT + * (typically 10 minutes). This method is related to the abort() method which provides an administrator + * thread a means to free any such threads in cases where the JDBC connection is accessible to the + * administrator thread. The setNetworkTimeout method will cover cases where there is no administrator + * thread, or it has no access to the connection. This method is severe in it's effects, and should be + * given a high enough value so it is never triggered before any more normal timeouts, + * such as transaction timeouts. + *

JDBC driver implementations may also choose to support the setNetworkTimeout method to impose + * a limit on database response time, in environments where no network is present. + *

Drivers may internally implement some or all of their API calls with multiple internal driver-database + * transmissions, and it is left to the driver implementation to determine whether the limit will be + * applied always to the response to the API call, or to any single request made during the API call. + *

This method can be invoked more than once, such as to set a limit for an area of JDBC code, + * and to reset to the default on exit from this area. Invocation of this method has no impact on + * already outstanding requests. + *

The Statement.setQueryTimeout() timeout value is independent of the timeout value specified in + * setNetworkTimeout. If the query timeout expires before the network timeout then the statement execution + * will be canceled. If the network is still active the result will be that both the statement and connection + * are still usable. However if the network timeout expires before the query timeout or if the statement timeout + * fails due to network problems, the connection will be marked as closed, any resources held by the connection + * will be released and both the connection and statement will be unusable. + *

When the driver determines that the setNetworkTimeout timeout value has expired, the JDBC driver marks + * the connection closed and releases any resources held by the connection. + *

This method checks to see that there is an SQLPermission object before allowing the method to proceed. + * If a SecurityManager exists and its checkPermission method denies calling setNetworkTimeout, this method + * throws a java.lang.SecurityException. + *@param executor - The Executor implementation which will be used by setNetworkTimeout. + *@param milliseconds - The time in milliseconds to wait for the database operation to complete. If the + * JDBC driver does not support milliseconds, the JDBC driver will round the value up to the nearest second. + * If the timeout period expires before the operation completes, a SQLException will be thrown. A value of + * 0 indicates that there is not timeout for database operations. + * @throws SQLException - if a database access error occurs, this method is called on a closed connection, + * the executor is null, or the value specified for seconds is less than 0. + * @throws SecurityException - if a security manager exists and its checkPermission method denies calling + * setNetworkTimeout. + * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method + * @also SecurityManager.checkPermission(java.security.Permission), Statement.setQueryTimeout(int), + * getNetworkTimeout(), abort(java.util.concurrent.Executor), Executor + +/* ifdef JDBC40 */ + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + // TODO JDBC41 Auto-generated method stub + + // Make sure value is not negative + if (milliseconds < 0) { + JDError.throwSQLException(JDError.EXC_PARAMETER_TYPE_INVALID); + } + + // Check for null executor + if (executor == null) { + JDError.throwSQLException(JDError.EXC_PARAMETER_TYPE_INVALID); + } + + // Check for authority + SecurityManager security = System.getSecurityManager(); + if (security != null) { + SQLPermission sqlPermission = new SQLPermission("setNetworkTimeout"); + security.checkPermission(sqlPermission); + } + + checkOpen (); + + try { + server_.setSoTimeout(milliseconds); + } catch (java.net.SocketException socketException) { + JDError.throwSQLException(JDError.EXC_COMMUNICATION_LINK_FAILURE, socketException); + } + + } +/* endif */ + + /** + *Sets the given schema name to access. + *

+ * Calling setSchema has no effect on previously created or prepared Statement objects. + * For the toolbox driver, the DBMS prepare operation takes place immediately when the + * Connection method prepareStatement or prepareCall is invoked. + * For maximum portability, setSchema should be called before a Statement is created or prepared. + * + * @param schema The name of the schema to use for the connection + * @throws SQLException If a database access error occurs or this method is + * called on a closed connection + * + */ + public void setSchema(String schema) throws SQLException { + checkOpen (); + PreparedStatement ps = prepareStatement("SET CURRENT SCHEMA ? "); + if (schema.length() > 0 && schema.charAt(0) == '"') { + // If delimited name pass as is + } else { + // Name is not delimited, make sure it is upper case + schema = schema.toUpperCase(); + } + ps.setString(1, schema); + ps.executeUpdate(); + ps.close(); + } + + /** + * Is SQL cancel used for the query timeout mechanism + * @return true if cancel will be used as the query timeout mechanism + */ + protected boolean isQueryTimeoutMechanismCancel() { + return queryTimeoutMechanism_ == QUERY_TIMEOUT_CANCEL; + } + + + /** + * Setup the variableFieldCompression flags @K3A + */ + void setupVariableFieldCompression() { + if (!variableFieldCompressionPropertyEvaluated_) { + + boolean variableFieldInsertCompressionAvailable = false; + if (serverFunctionalLevel_ >= 16) { + variableFieldInsertCompressionAvailable = true; + } + if (serverFunctionalLevel_ >= 14) { + String property = null; + try { + property = getProperties().getString( + JDProperties.VARIABLE_FIELD_COMPRESSION); + } catch (Exception e) { + // Just use defaults + } + if (property == null) + property = "default"; + property = property.toLowerCase().trim(); + if ("false".equals(property)) { + useVariableFieldCompression_ = false; + useVariableFieldInsertCompression_ = false; + variableFieldCompressionPropertyEvaluated_ = true; + } else if ("true".equals(property)) { + useVariableFieldCompression_ = true; + useVariableFieldInsertCompression_ = false; + variableFieldCompressionPropertyEvaluated_ = true; + } else if ("insert".equals(property)) { + useVariableFieldCompression_ = false; + useVariableFieldInsertCompression_ = variableFieldInsertCompressionAvailable; + variableFieldCompressionPropertyEvaluated_ = true; + } else { + // Default is to use all possible compression + useVariableFieldCompression_ = true; + useVariableFieldInsertCompression_ = variableFieldInsertCompressionAvailable; + variableFieldCompressionPropertyEvaluated_ = true; + } + } else { + // server does not support any form of compression + useVariableFieldCompression_ = false; + useVariableFieldInsertCompression_ = false; + variableFieldCompressionPropertyEvaluated_ = true; + } + } + } + + boolean useVariableFieldCompression() { + if (!variableFieldCompressionPropertyEvaluated_) { + setupVariableFieldCompression(); + } + return useVariableFieldCompression_; + } + + boolean useVariableFieldInsertCompression() { + if (!variableFieldCompressionPropertyEvaluated_) { + setupVariableFieldCompression(); + } + return useVariableFieldInsertCompression_; + } + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCConnectionHandle.java b/jdbc40/com/ibm/as400/access/AS400JDBCConnectionHandle.java new file mode 100644 index 000000000..b7ff0753f --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCConnectionHandle.java @@ -0,0 +1,2051 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCConnectionHandle.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-2006 International Business Machines Corporation and +// others. All rights reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +package com.ibm.as400.access; + +import javax.sql.ConnectionEvent; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +/* ifdef JDBC40 */ +import java.sql.SQLClientInfoException; +/* endif */ +import java.sql.Clob; +import java.sql.Connection; //@A5A +import java.sql.DatabaseMetaData; +/* ifdef JDBC40 */ +import java.sql.NClob; +/* endif */ +import java.sql.PreparedStatement; +/* ifdef JDBC40 */ +import java.sql.SQLXML; +/* endif */ +import java.sql.Savepoint; //@A6A +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Map; +import java.util.Properties; //@pda client info +/* ifdef JDBC40 */ +import java.util.concurrent.Executor; +/* endif */ + +/** +* The AS400JDBCConnectionHandle class represents an AS400JDBCConnection object +* that can be used in a AS400JDBCPooledConnection. +* +*

Creating a handle to a connection object allows the connection to be reused. +* The connection handle acts like a normal Connection object and should be closed +* after an application is done using it so it can be reused. +* +*

+* The following example obtains a connection handle to a pooled connection. +*

+* // Create a data source for making the connection. +* AS400JDBCConnectionPoolDataSource dataSource = new AS400JDBCConnectionPoolDataSource("CheeseDataBase"); +* datasource.setServerName("myAS400"); +* datasource.setUser("Mickey Mouse"); +* datasource.setPassword("IAMNORAT"); +* +* // Get a PooledConnection and get the connection handle to the database. +* AS400JDBCPooledConnection pooledConnection = datasource.getPooledConnection(); +* Connection connection = pooledConnection.getConnection(); +* +* ... work with the handle as if it is a normal connection. +* +* // Close the connection handle to it make available again for reuse. +* connection.close(); +*
+* +**/ +public class AS400JDBCConnectionHandle +/* ifdef JDBC40 */ +extends ToolboxWrapper +/* endif */ +implements Connection //@A5A +//@A5D extends AS400JDBCConnection +{ + + static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others."; + + private AS400JDBCPooledConnection pooledConnection_ = null; + private AS400JDBCConnection connection_ = null; + + /** + * Constructs an AS400JDBCConnectionHandle object. + * @param pooledConnection The pooled connection from which the handle originated. + * @param connection The physical connection that the handle represents. + **/ + AS400JDBCConnectionHandle(AS400JDBCPooledConnection pooledConnection, AS400JDBCConnection connection) + { + if (pooledConnection == null) + throw new NullPointerException("pooledConnection"); + pooledConnection_ = pooledConnection; + + if (connection == null) + throw new NullPointerException("connection"); + connection_ = connection; + } + + //@pda handle + /** + * Invalidates the connection. + * A AS400JDBCPooledConnection can get expired and moved back to available queue. So this + * handle class needs a way for AS400JDBCPooledConnection to notify it of this change in state. + * This way, when finalize() is called by GC we will not try to double-close the connection. + * Without this method, it is possible for two handles to have references to the same pooledConnection. + **/ + void invalidate() + { + connection_ = null; + pooledConnection_ = null; + } + + /** + * Checks that the specified SQL statement can be executed. + * This decision is based on the access specified by the caller + * and the read only mode. + * + * @param sqlStatement The SQL statement. + * @exception SQLException If the statement cannot be executed. + **/ + void checkAccess (JDSQLStatement sqlStatement) throws SQLException + { + validateConnection(); + try { + connection_.checkAccess(sqlStatement); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + + /** + * Checks that the connection is open. Public methods + * that require an open connection should call this first. + * + * @exception SQLException If the connection is not open. + **/ + void checkOpen() throws SQLException + { + validateConnection(); + try { + connection_.checkOpen(); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + + /** + * Clears all warnings that have been reported for the connection. + * After this call, getWarnings() returns null until a new warning + * is reported for the connection. + * + * @exception SQLException If an error occurs. + **/ + public void clearWarnings() throws SQLException + { + validateConnection(); + connection_.clearWarnings(); + } + + + + /** + * Closes the handle to the connection. This does not close the + * underlying physical connection to the database. The handle is + * set to an unuseable state. + * + * @exception SQLException If an error occurs. + **/ + public synchronized void close() throws SQLException + { + if (connection_ == null) return; + + try { + // Rollback and close the open statements. + // Note: Leave the physical connection open, so it can get re-used. + connection_.pseudoClose(); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + finally { + // notify the pooled connection. + pooledConnection_.fireConnectionCloseEvent(new ConnectionEvent(pooledConnection_)); + + connection_ = null; + pooledConnection_ = null; + } + } + + /** + * Commits all changes made since the previous commit or + * rollback and releases any database locks currently held by + * the connection. This has no effect when the connection + * is in auto-commit mode. + * + * @exception SQLException If the connection is not open + * or an error occurs. + **/ + public void commit() throws SQLException + { + validateConnection(); + try { + connection_.commit(); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Creates a Statement object for executing SQL statements without + * parameters. If the same SQL statement is executed many times, it + * is more efficient to use prepareStatement(). + * + *

Result sets created using the statement will be type + * ResultSet.TYPE_FORWARD_ONLY and concurrency + * ResultSet.CONCUR_READ_ONLY. + * + * @return The statement object. + * + * @exception SQLException If the connection is not open, the maximum number + * of statements for this connection has been reached, or an error occured. + **/ + public Statement createStatement() throws SQLException + { + validateConnection(); + return connection_.createStatement(); + } + + + /** + * Creates a Statement object for executing SQL statements without + * parameters. If the same SQL statement is executed many times, it + * is more efficient to use prepareStatement(). + * + * @param resultSetType The result set type. Valid values are: + *

+ * @param resultSetConcurrency The result set concurrency. Valid values are: + * + * @return The statement object. + * + * @exception SQLException If the connection is not open, the maximum number of statements + * for this connection has been reached, the result type or currency + * is not supported, or an error occured. + **/ + public Statement createStatement (int resultSetType, int resultSetConcurrency) throws SQLException + { + validateConnection(); + return connection_.createStatement(resultSetType, resultSetConcurrency); + } + + + //@A6A + /** + Creates a Statement object for executing SQL statements without + parameters. If the same SQL statement is executed many times, it + is more efficient to use prepareStatement(). + +

Full functionality of this method requires support in OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, the value for + resultSetHoldability will be ignored. + + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @param resultSetHoldability The result set holdability. Valid values are: + + @return The statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not supported, + or an error occurs. + @since Modification 5 + **/ + public Statement createStatement (int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + validateConnection(); + return connection_.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + + /** + * Closes the connection if not explicitly closed by the caller. + * + * @exception Throwable If an error occurs. + **/ + protected void finalize () + throws Throwable + { + //@A5D Removed validateConnection() because it was throwing SQL08003 exceptions if + //@A5D connection_ was null by the time the garbage collector ran. From a finalizer, + //@A5D we don't want to be throwing exceptions. + //@A5D validateConnection(); + //@A5D connection_.finalize(); + try + { //@A5A //@A5A + close(); //@A5A + } //@A5A + catch (SQLException e) //@A5A + { //@A5A + if (JDTrace.isTraceOn()) //@A5A + JDTrace.logInformation (this, "Finalize on a connection handle threw exception: " + e.getMessage()); //@A5A + } //@A5A + } + + + //@CPMa + /** + * If the exception is a fatal connection error, fires a connectionErrorOccurred event. + * We're looking for any kind of error that would indicate that the connection + * should not be re-used after it's returned to the connection pool. + **/ + private final void fireEventIfErrorFatal(SQLException e) + { + String sqlState = e.getSQLState(); + if (sqlState.equals(JDError.EXC_ACCESS_MISMATCH) || + sqlState.equals(JDError.EXC_CONNECTION_NONE) || + sqlState.equals(JDError.EXC_CONNECTION_REJECTED) || + sqlState.equals(JDError.EXC_CONNECTION_UNABLE) || + sqlState.equals(JDError.EXC_COMMUNICATION_LINK_FAILURE) || + sqlState.equals(JDError.EXC_INTERNAL) || + sqlState.equals(JDError.EXC_SERVER_ERROR) || + sqlState.equals(JDError.EXC_RDB_DOES_NOT_EXIST)) + { + pooledConnection_.fatalConnectionErrorOccurred_ = true; + pooledConnection_.fireConnectionErrorEvent(new ConnectionEvent(pooledConnection_, e)); + } + } + + /** + * Returns the AS400 object for this connection. + * + * @return The AS400 object. + **/ + AS400Impl getAS400 () + throws SQLException // @A3A + { + validateConnection(); + return connection_.getAS400(); + } + + /** + * Returns the auto-commit state. + * + * @return true if the connection is in auto-commit mode; false otherwise. + * @exception SQLException If the connection is not open. + **/ + public boolean getAutoCommit() throws SQLException + { + validateConnection(); + return connection_.getAutoCommit(); + } + + //@cc1 + /** + * This method returns the concurrent access resolution setting. + * This method has no effect on IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @return The concurrent access resolution setting. Possible return valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public int getConcurrentAccessResolution () throws SQLException + { + validateConnection(); + return connection_.getConcurrentAccessResolution(); + } + + /** + * Returns the catalog name. + * + * @return The catalog name. + * @exception SQLException If the connection is not open. + **/ + public String getCatalog () + throws SQLException + { + validateConnection(); + return connection_.getCatalog(); + } + + + + /** + * Returns the converter for this connection. + * + * @return The converter. + **/ + ConvTable getConverter () //@P0C + throws SQLException // @A3A + { + validateConnection(); + return connection_.converter_; //@P0C + } + + /** + * Returns the converter for the specified CCSID, unless + * it is 0 or -1 (i.e. probably set for a non-text field), in + * which case it returns the converter for this connection. + * This is useful for code that handles all types of fields + * in a generic manner. + * + * @param ccsid The CCSID. + * @return The converter. + * @exception SQLException If the CCSID is not valid. + **/ + ConvTable getConverter (int ccsid) //@P0C + throws SQLException + { + validateConnection(); + return connection_.getConverter(ccsid); + } + + + + /** + * Returns the default SQL schema. + * + * @return The default SQL schema, or QGPL if none was specified. + **/ + String getDefaultSchema () + throws SQLException // @A3A + { + validateConnection(); + return connection_.getDefaultSchema(); + } + + // @A1D /** + // @A1D * Returns the graphic converter for this connection. + // @A1D * + // @A1D * @return The graphic converter. + // @A1D * @exception SQLException If no graphic converter was loaded. + // @A1D **/ + // @A1D ConverterImplRemote getGraphicConverter () throws SQLException + // @A1D { + // @A1D validateConnection(); + // @A1D return connection_.getGraphicConverter(); + // @A1D } + + + //@A6A + /** + Returns the holdability of ResultSets created from this connection. + + @return The cursor holdability. Valid values are ResultSet.HOLD_CURSORS_OVER_COMMIT and + ResultSet.CLOSE_CURSORS_AT_COMMIT. The holdability is derived in this order + of precedence: + + Full functionality of #1 requires support in OS/400 + V5R2 or IBM i. If connecting to OS/400 V5R1 or earlier, + the value specified on this method will be ignored and the default holdability + will be the value of #2. + + @exception SQLException If the connection is not open. + @since Modification 5 + **/ + public int getHoldability () + throws SQLException + { + validateConnection(); + return connection_.getHoldability(); + } + + + //@A4A + /** + * Returns the DatabaseMetaData object that describes the + * connection's tables, supported SQL grammar, stored procedures, + * capabilities and more. + * + * @return The metadata object. + * + * @exception SQLException If an error occurs. + **/ + public DatabaseMetaData getMetaData () + throws SQLException + { + // We allow a user to get this object even if the + // connection is closed. + //@pdc above comment not true anymore + validateConnection(); //@pda since adding invalidate(), connection_ can be null + return connection_.getMetaData(); + } + + + /** + * Returns the connection properties. + * + * @return The connection properties. + **/ + JDProperties getProperties () + throws SQLException // @A3A + { + validateConnection(); + return connection_.getProperties(); + } + + /** + * Returns the job identifier of the host server job corresponding to this connection. + * Every JDBC connection is associated with a host server job on the system. The + * format is: + * + * + *

Note: Since this method is not defined in the JDBC Connection interface, + * you typically need to cast a Connection object returned from PooledConnection.getConnection() + * to an AS400JDBCConnectionHandle in order to call this method: + *

+  *  String serverJobIdentifier = ((AS400JDBCConnectionHandle)connection).getServerJobIdentifier();
+  *  
+ * + * @return The server job identifier, or null if not known. + * @exception SQLException If the connection is not open. + **/ + public String getServerJobIdentifier() throws SQLException + { + validateConnection(); + return connection_.getServerJobIdentifier(); + } + + //@pda + /** + Returns the system object which is managing the connection to the system. +

Warning: This method should be used with extreme caution. This bypasses + the normal connection pool's connection reclaiming mechanisms. +

Note: Since this method is not defined in the JDBC Connection interface, + you typically need to cast a Connection object to AS400JDBCConnectionHandle in order + to call this method: +

+  AS400 system = ((AS400JDBCConnectionHandle)connection).getSystem();
+  
+ + @return The system. + **/ + public AS400 getSystem() + { + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "Warning: returning pooled connection's AS400 object directly to user."); + return connection_.getSystem(); + } + + + /** + * Returns the transaction isolation level. + * + * @return The transaction isolation level. Possible + * values are: + * + * + * @exception SQLException If the connection is not open. + **/ + public int getTransactionIsolation() throws SQLException + { + validateConnection(); + return connection_.getTransactionIsolation(); + } + + /** + * Returns the type map. + * + *

This driver does not support the type map. + * + * @return The type map. + * @exception SQLException This exception is always thrown. + **/ + public Map getTypeMap() throws SQLException + { + validateConnection(); + return connection_.getTypeMap(); + } + + + /** + * Returns the URL for the connection's database. + * + * @return The URL for the database. + **/ + String getURL () + throws SQLException // @A3A + { + validateConnection(); + return connection_.getURL(); + } + + /** + * Returns the user name as currently signed on to the system. + * + * @return The user name. + **/ + String getUserName () + throws SQLException // @A3A + { + validateConnection(); + return connection_.getUserName(); + } + + + /** + * Returns the VRM. + **/ + int getVRM() + throws SQLException // @A3A + { + validateConnection(); + return connection_.getVRM(); + } + + /** + * Returns the first warning reported for the connection. + * Subsequent warnings may be chained to this warning. + * + * @return The first warning or null if no warnings + * have been reported. + * + * @exception SQLException If an error occurs. + **/ + public SQLWarning getWarnings() throws SQLException + { + validateConnection(); + return connection_.getWarnings(); + } + + /** + * Indicates if the specified cursor name is already used + * in the connection. + * + * @return true if the cursor name is already used; false otherwise. + **/ + boolean isCursorNameUsed (String cursorName) + throws SQLException // @A3A + { + validateConnection(); + return connection_.isCursorNameUsed(cursorName); + } + + /** + * Indicates if the connection is closed. + * + * @return true if the connection is closed; false otherwise. + * @exception SQLException If an error occurs. + **/ + public boolean isClosed() throws SQLException + { + if (connection_ == null) + return true; + else + return false; + } + + + + /** + * Indicates if the connection is in read-only mode. + * + * @return true if the connection is in read-only mode; false otherwise. + * @exception SQLException If the connection is not open. + **/ + public boolean isReadOnly() throws SQLException + { + validateConnection(); + return connection_.isReadOnly(); + } + + /** + * Returns the native form of an SQL statement without + * executing it. The JDBC driver converts all SQL statements + * from the JDBC SQL grammar into the native DB2 for IBM i + * SQL grammar prior to executing them. + * + * @param sql The SQL statement in terms of the JDBC SQL grammar. + * @return The translated SQL statement in the native + * DB2 for IBM i SQL grammar. + * + * @exception SQLException If the SQL statement has a syntax error. + **/ + public String nativeSQL (String sql) throws SQLException + { + validateConnection(); + return connection_.nativeSQL(sql); + } + + /** + * Notifies the connection that a statement in its context has been closed. + * + * @param statement The statement. + * @param id The statement's id. + **/ + void notifyClose (AS400JDBCStatement statement, int id) + throws SQLException // @A3A + { + validateConnection(); + connection_.notifyClose(statement, id); + } + + /** + * Posts a warning for the connection. + * + * @param sqlWarning The warning. + **/ + void postWarning (SQLWarning sqlWarning) + throws SQLException // @A3A + { + validateConnection(); + connection_.postWarning(sqlWarning); + } + + /** + * Precompiles an SQL stored procedure call with optional input + * and output parameters and stores it in a CallableStatement + * object. This object can be used to efficiently call the SQL + * stored procedure multiple times. + * + *

Result sets created using the statement will be type + * ResultSet.TYPE_FORWARD_ONLY and concurrency + * ResultSet.CONCUR_READ_ONLY. + * + * @param sql The SQL stored procedure call. + * @return The callable statement object. + * + * @exception SQLException If the connection is not open, + * the maximum number of statements + * for this connection has been reached, or an + * error occurs. + **/ + public CallableStatement prepareCall (String sql) throws SQLException + { + validateConnection(); + return connection_.prepareCall(sql); + } + + /** + * Precompiles an SQL stored procedure call with optional input + * and output parameters and stores it in a CallableStatement + * object. This object can be used to efficiently call the SQL + * stored procedure multiple times. + * + * @param sql The SQL statement. + * @param resultSetType The result set type. Valid values are: + *

+ * @param resultSetConcurrency The result set concurrency. Valid values are: + * + * @return The prepared statement object. + * + * @exception SQLException If the connection is not open, the maximum number of statements + * for this connection has been reached, the result type or currency + * is not valid, or an error occurs. + **/ + public CallableStatement prepareCall (String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + validateConnection(); + return connection_.prepareCall(sql, resultSetType, resultSetConcurrency); + } + + + //@G4A JDBC 3.0 + /** + Precompiles an SQL stored procedure call with optional input + and output parameters and stores it in a CallableStatement + object. This object can be used to efficiently call the SQL + stored procedure multiple times. + +

Full functionality of this method requires support in OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, the value for + resultSetHoldability will be ignored. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: +

+ @param resultSetConcurrency The result set concurrency. Valid values are: + + @return The prepared statement object. + @param resultSetHoldability The result set holdability. Valid values are: + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not valid, + or an error occurs. + @since Modification 5 + **/ + public CallableStatement prepareCall (String sql, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + validateConnection(); + return connection_.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement multiple times. + * + *

Result sets created using the statement will be type + * ResultSet.TYPE_FORWARD_ONLY and concurrency + * ResultSet.CONCUR_READ_ONLY. + * + * @param sql The SQL statement. + * @return The prepared statement object. + * + * @exception SQLException If the connection is not open, + * the maximum number of statements + * for this connection has been reached, or an + * error occurs. + **/ + public PreparedStatement prepareStatement (String sql) throws SQLException + { + validateConnection(); + return connection_.prepareStatement(sql); + } + + + + //@A6A + /** +Precompiles an SQL statement with optional input parameters +and stores it in a PreparedStatement object. This object can +be used to efficiently execute this SQL statement +multiple times. + +

This method requires OS/400 V5R2 or IBM i. If connecting to OS/400 V5R1 or earlier, an exception will be +thrown. + +

Result sets created using the statement will be type +ResultSet.TYPE_FORWARD_ONLY and concurrency +ResultSet.CONCUR_READ_ONLY. + +@param sql The SQL statement. +@param autoGeneratedKeys Whether to return auto generated keys. Valid values are: +

+@return The prepared statement object. + +@exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, + if connecting to OS/400 V5R1 or earlier, + an error occurs. +@since Modification 5 +**/ + public PreparedStatement prepareStatement (String sql, int autoGeneratedKeys) + throws SQLException + { + validateConnection(); + return connection_.prepareStatement(sql, autoGeneratedKeys); + } + + + // @A6A + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement + * multiple times. + * + *

This method is not supported. An SQLException is always thrown. + * + * @param sql The SQL statement. + * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row or rows. + * @return An SQLException is always thrown. This method is not supported. + * @exception java.sql.SQLException - Always thrown because the Toolbox JDBC driver does does not support this method. + * @since Modification 5 + **/ + public PreparedStatement prepareStatement (String sql, int[] columnIndexes) + throws SQLException + { + validateConnection(); + return connection_.prepareStatement(sql, columnIndexes); + } + + + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement + * multiple times. + * + * @param sql The SQL statement. + * @param resultSetType The result set type. Valid values are: + *

+ * @param resultSetConcurrency The result set concurrency. Valid values are: + * + * @return The prepared statement object. + * + * @exception SQLException If the connection is not open, + * the maximum number of statements + * for this connection has been reached, the + * result type or currency is not valid, + * or an error occurs. + **/ + public PreparedStatement prepareStatement (String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + validateConnection(); + return connection_.prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + + //@A6A + /** + Precompiles an SQL statement with optional input parameters + and stores it in a PreparedStatement object. This object can + be used to efficiently execute this SQL statement + multiple times. + + @param sql The SQL statement. + @param resultSetType The result set type. Valid values are: + + @param resultSetConcurrency The result set concurrency. Valid values are: + + @param resultSetHoldability The result set holdability. Valid values are: + + @return The prepared statement object. + + @exception SQLException If the connection is not open, + the maximum number of statements + for this connection has been reached, the + result type, currency, or holdability is not valid, + or an error occurs. + **/ + public PreparedStatement prepareStatement (String sql, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException + { + validateConnection(); + return connection_.prepareStatement (sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + + // @A6A + /** + * Precompiles an SQL statement with optional input parameters + * and stores it in a PreparedStatement object. This object can + * be used to efficiently execute this SQL statement + * multiple times. + * + *

This method is not supported. An SQLException is always thrown. + * + * @param sql The SQL statement. + * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or rows. + * @return An SQLException is always thrown. This method is not supported. + * @exception java.sql.SQLException - Always thrown because the Toolbox JDBC driver does does not support this method. + * @since Modification 5 + **/ + public PreparedStatement prepareStatement (String sql, String[] columnNames) + throws SQLException + { + // Auto generated keys now supported for some releases.. Let the connection + // handle the exception. + + validateConnection(); + return connection_.prepareStatement(sql, columnNames); + } + + + // @A6A + /** + * Removes the given Savepoint object from the current transaction. + * Any reference to the savepoint after it has been removed will + * cause an SQLException to be thrown. + * + * @param savepoint the savepoint to be removed. + * + * @exception SQLException if a database access error occurs or the given Savepoint + * is not a valid savepoint in the current transaction. + * + * @since Modification 5 + **/ + public void releaseSavepoint(Savepoint savepoint) + throws SQLException + { + validateConnection(); + try { + connection_.releaseSavepoint(savepoint); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + /** + * Drops all changes made since the previous commit or + * rollback and releases any database locks currently held by + * the connection. This has no effect when the connection + * is in auto-commit mode. + * + * @exception SQLException If the connection is not open + * or an error occurs. + **/ + public void rollback () throws SQLException + { + validateConnection(); + try { + connection_.rollback(); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + // @A6A + /** + * Undoes all changes made after the specified Savepoint was set. + * + * @param savepoint the savepoint to be rolled back to. + * + * @exception SQLException if a database access error occurs, the Savepoint + * is no longer valid, or this Connection + * is currently in auto-commit mode. + * @since Modification 5 + **/ + public void rollback(Savepoint savepoint) + throws SQLException + { + validateConnection(); + try { + connection_.rollback(savepoint); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + /** + * Sends a request data stream to the system using the + * connection's id and does not expect a reply. + * + * @param request The request. + * + * @exception SQLException If an error occurs. + **/ + void send (DBBaseRequestDS request) throws SQLException + { + validateConnection(); + try { + connection_.send (request); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Sends a request data stream to the system and does not + * expect a reply. + * + * @param request The request. + * @param id The id. + * + * @exception SQLException If an error occurs. + **/ + void send (DBBaseRequestDS request, int id) throws SQLException + { + validateConnection(); + try { + connection_.send(request, id); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Sends a request data stream to the system and does not + * expect a reply. + * + * @param request The request. + * @param id The id. + * @param leavePending Indicates if the request should + * be left pending. This indicates + * whether or not to base the next + * request on this one. + * + * @exception SQLException If an error occurs. + **/ + void send (DBBaseRequestDS request, int id, boolean leavePending) throws SQLException + { + validateConnection(); + try { + connection_.send(request, id, leavePending); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + // @A2D /** + // @A2D * Sends a request data stream to the system and discards the reply. + // @A2D * + // @A2D * @param request The request. + // @A2D * @param id The id. + // @A2D * @param leavePending Indicates if the request should + // @A2D * be left pending. This indicates + // @A2D * whether or not to base the next + // @A2D * request on this one. + // @A2D * + // @A2D * @exception SQLException If an error occurs. + // @A2D **/ + // @A2D void sendAndDiscardReply (DBBaseRequestDS request, int id) throws SQLException + // @A2D { + // @A2D validateConnection(); + // @A2D connection_.sendAndDiscardReply(request, id); + // @A2D } + + /** + * Sends a request data stream to the system using the + * connection's id and returns the corresponding reply from + * the system. + * + * @param request The request. + * @return The reply. + * + * @exception SQLException If an error occurs. + **/ + DBReplyRequestedDS sendAndReceive (DBBaseRequestDS request) throws SQLException + { + validateConnection(); + try { + return connection_.sendAndReceive(request); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Sends a request data stream to the system and returns the + * corresponding reply from the system. + * + * @param request The request. + * @param id The id. + * @return The reply. + * + * @exception SQLException If an error occurs. + **/ + DBReplyRequestedDS sendAndReceive (DBBaseRequestDS request, int id) throws SQLException + { + validateConnection(); + try { + return connection_.sendAndReceive(request, id); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Sets the auto-commit mode. If the connection is in auto-commit + * mode, then all of its SQL statements are executed and committed + * as individual transactions. Otherwise, its SQL statements are + * grouped into transactions that are terminated by either a commit + * or rollback. + * + *

By default, the connection is in auto-commit mode. The + * commit occurs when the statement execution completes or the + * next statement execute occurs, whichever comes first. In the + * case of statements returning a result set, the statement + * execution completes when the last row of the result set has + * been retrieved or the result set has been closed. In advanced + * cases, a single statement may return multiple results as well + * as output parameter values. Here the commit occurs when all results + * and output parameter values have been retrieved. + * + * @param autoCommit true to turn on auto-commit mode, false to + * turn it off. + * + * @exception SQLException If the connection is not open + * or an error occurs. + **/ + public void setAutoCommit (boolean autoCommit) throws SQLException + { + validateConnection(); + try { + connection_.setAutoCommit(autoCommit); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + //@cc1 + /** + * This method sets concurrent access resolution. This method overrides the setting of ConcurrentAccessResolution on the datasource or connection + * URL properties. This changes the setting for this connection only. This method has no effect on + * IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @param concurrentAccessResolution The current access resolution setting. Possible valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public void setConcurrentAccessResolution (int concurrentAccessResolution) throws SQLException + { + validateConnection(); + connection_.setConcurrentAccessResolution(concurrentAccessResolution); + } + + /** + Sets the eWLM Correlator. It is assumed a valid correlator value is used. + If the value is null, all ARM/eWLM implementation will be turned off. + eWLM correlators require i5/OS V5R3 or later systems. This request is ignored when running to OS/400 V5R2 or earlier systems. + + @param bytes The eWLM correlator value + **/ + public void setDB2eWLMCorrelator(byte[] bytes) + throws SQLException //@eWLM + { + validateConnection(); + connection_.setDB2eWLMCorrelator(bytes); + } + + /** + * This method is not supported. + * @exception SQLException If the connection is not open. + **/ + public void setCatalog (String catalog) throws SQLException + { + validateConnection(); + connection_.setCatalog(catalog); + } + + /** + * Sets whether the connection is being used for DRDA. + * + * @param drda true if the connection is being used for DRDA; false otherwise. + **/ + void setDRDA (boolean drda) + throws SQLException // @A3A + { + validateConnection(); + connection_.setDRDA(drda); + } + + + //@A6A + /** + Sets the holdability of ResultSets created from this connection. + +

Full functionality of this method requires OS/400 V5R2 + or IBM i. If connecting to OS/400 V5R1 or earlier, all + cursors for the connection will be changed to the value of the variable + holdability. + + @param holdability The cursor holdability. + Valid values are ResultSet.HOLD_CURSORS_OVER_COMMIT or + ResultSet.CLOSE_CURSORS_AT_COMMIT. + + @exception SQLException If the connection is not open + or the value passed in is not valid. + @since Modification 5 + **/ + public void setHoldability (int holdability) + throws SQLException + { + validateConnection(); + connection_.setHoldability(holdability); + } + + + /** + * Sets the connection properties. + **/ + void setProperties (JDDataSourceURL dataSourceUrl, JDProperties properties, AS400 as400) + throws SQLException + { + validateConnection(); + try { + connection_.setProperties(dataSourceUrl, properties, as400); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + + /** + * Sets the properties. + **/ + void setProperties (JDDataSourceURL dataSourceUrl, JDProperties properties, AS400Impl as400) + throws SQLException + { + validateConnection(); + try { + connection_.setProperties(dataSourceUrl, properties, as400); + } + catch (SQLException e) { + fireEventIfErrorFatal(e); + throw e; + } + } + + /** + * Sets the read-only mode. This will provide read-only + * access to the database. Read-only mode can be useful by + * enabling certain database optimizations. If the caller + * specified "read only" or "read call" for the "access" property, + * then the read-only mode cannot be set to false. The read-only + * mode cannot be changed while in the middle of a transaction. + * + * @param readOnly true to set the connection to read-only mode; + * false to set the connection to read-write mode. + * + * @exception SQLException If the connection is not open, + * a transaction is active, or the + * "access" property is set to "read + * only". + **/ + public void setReadOnly (boolean readOnly) + throws SQLException + { + validateConnection(); + connection_.setReadOnly(readOnly); + } + + + // @A6A + /** + * Creates an unnamed savepoint in the current transaction and returns the new Savepoint object that represents it. + *

+ * + * @return The new Savepoint object. + * @exception SQLException if a database access error occurs or this Connection object is currently in auto-commit mode. + * @since Modification 5 + **/ + public Savepoint setSavepoint() + throws SQLException + { + validateConnection(); + return connection_.setSavepoint(); + } + + + // @A6 + /** + * Creates a named savepoint in the current transaction and returns the new Savepoint object that represents it. + * + * @param name A String containing the name of the savepoint + * @return The new Savepoint object. + * @exception SQLException if a database access error occurs or this Connection object is currently in auto-commit mode. + * @since Modification 5 + **/ + public Savepoint setSavepoint(String name) + throws SQLException + { + validateConnection(); + return connection_.setSavepoint(name); + } + + /** + * + **/ + void setSystem (AS400 as400) + throws SQLException // @A3A + { + validateConnection(); + connection_.setSystem(as400); + } + + /** + * Sets the transaction isolation level. The transaction + * isolation level cannot be changed while in the middle of + * a transaction. + * + *

JDBC and DB2 for IBM i use different terminology for transaction + * isolation levels. The following table provides a terminology + * mapping: + * + *

+ * + * + * + * + * + *
DB2 for IBM i isolation levelJDBC transaction isolation level
*CHG TRANSACTION_READ_UNCOMMITTED
*CS TRANSACTION_READ_COMMITTED
*ALL TRANSACTION_READ_REPEATABLE_READ
*RR TRANSACTION_SERIALIZABLE
+ * + * @param level The transaction isolation level. Possible values are: + *

+ * + * @exception SQLException If the connection is not open, the input level is not valid + * or unsupported, or a transaction is active. + **/ + public void setTransactionIsolation (int level) + throws SQLException + { + validateConnection(); + connection_.setTransactionIsolation(level); + } + + + + /** + * Sets the type map to be used for distinct and structured types. + * + *

Note: Distinct types are supported by DB2 for IBM i, but + * are not externalized by the IBM Toolbox for Java JDBC driver. + * In other words, distinct types behave as if they are the underlying + * type. Structured types are not supported by DB2 for IBM i. + * Consequently, this driver does not support the type map. + * + * @param typeMap The type map. + * @exception SQLException This exception is always thrown. + **/ + public void setTypeMap (Map typeMap) throws SQLException + { + validateConnection(); + connection_.setTypeMap(typeMap); + } + + + + /** + * Returns the connection's catalog name. + * This is the name of the IBM i system. + * @return The catalog name. + **/ + public String toString () + { + if (connection_ != null) // @A3C + return connection_.toString(); + else // @A3A + return super.toString(); // @A3A + } + + + + /** + * Indicates if the connection is using extended formats. + * @return true if the connection is using extended formats, false otherwise. + **/ + boolean useExtendedFormats () + throws SQLException // @A3A + { + validateConnection(); + return connection_.useExtendedFormats(); + } + + + /** + * Validates that the connection has not been closed. + **/ + private void validateConnection() + throws SQLException // @A3A + { + if (connection_ == null) + { + // This would indicate that close() has been called on this handle. + // Note: It does _not_ indicate that the actual physical connection has experienced a fatal connection error. Therefore, we don't call fireConnectionErrorEvent() in this case. + JDTrace.logInformation (this, "The connection is closed."); // @A7C + JDError.throwSQLException (JDError.EXC_CONNECTION_NONE); // @A3C + } + } + //@pda jdbc40 + protected String[] getValidWrappedList() + { + return new String[] { "java.sql.Connection" }; //@pdc can't be a as400jdbcconnection wrapper because an attempt to cast as such would fail + } + + + //@PDA jdbc40 + /** + * Returns true if the connection has not been closed and is still valid. + * The driver shall submit a query on the connection or use some other + * mechanism that positively verifies the connection is still valid when + * this method is called. + *

+ * The query submitted by the driver to validate the connection shall be + * executed in the context of the current transaction. + * + * @param timeout - The time in seconds to wait for the database operation + * used to validate the connection to complete. If + * the timeout period expires before the operation + * completes, this method returns false. A value of + * 0 indicates a timeout is not applied to the + * database operation. Note that currently the timeout + * value is not used. + *

+ * @return true if the connection is valid, false otherwise + * @exception SQLException if a database access error occurs. + */ +/* ifdef JDBC40 */ + public boolean isValid(int timeout) throws SQLException + { + validateConnection(); + return connection_.isValid(timeout); + } +/* endif */ + + //@PDA jdbc40 + + // @PDA 550 client info + /** + * Sets the value of the connection's client info properties. The + * Properties object contains the names and values of the + * client info properties to be set. The set of client info properties + * contained in the properties list replaces the current set of client info + * properties on the connection. If a property that is currently set on the + * connection is not present in the properties list, that property is + * cleared. Specifying an empty properties list will clear all of the + * properties on the connection. See + * setClientInfo (String, String) for more information. + *

+ * If an error occurs in setting any of the client info properties, a + * ClientInfoException is thrown. The + * ClientInfoException contains information indicating which + * client info properties were not set. The state of the client information + * is unknown because some databases do not allow multiple client info + * properties to be set atomically. For those databases, one or more + * properties may have been set before the error occurred. + *

+ * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * + * @param properties + * the list of client info properties to set + *

+ * @throws SQLException + * if the database server returns an error while setting the + * clientInfo values on the database server + *

+ * see java.sql.Connection#setClientInfo(String, String) + * setClientInfo(String, String) + */ + public void setClientInfo(Properties properties) +/* ifdef JDBC40 */ + throws SQLClientInfoException +/* endif */ +/* ifndef JDBC40 + throws SQLException + endif */ + { +/* ifdef JDBC40 */ + try { +/* endif */ + validateConnection(); +/* ifdef JDBC40 */ + }catch(SQLException e) + { + SQLClientInfoException clientIE = new SQLClientInfoException(e.getMessage(), e.getSQLState(), null); + throw clientIE; + } +/* endif */ + + + connection_.setClientInfo(properties); + } /* setClientInfo */ + + + //@PDA 550 client info + /** + * Returns the value of the client info property specified by name. This + * method may return null if the specified client info property has not + * been set and does not have a default value. This method will also + * return null if the specified client info property name is not supported + * by the driver. + *

+ * Applications may use the DatabaseMetaData.getClientInfoProperties + * method to determine the client info properties supported by the driver. + *

+ * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @param name The name of the client info property to retrieve + *

+ * @return The value of the client info property specified + *

+ * @throws SQLException if the database server returns an error when + * fetching the client info value from the database. + *

+ * see java.sql.DatabaseMetaData#getClientInfoProperties + */ + public String getClientInfo(String name) throws SQLException + { + validateConnection(); + return connection_.getClientInfo(name); + } + + + + //@PDA 550 client info + /** + * Returns a list containing the name and current value of each client info + * property supported by the driver. The value of a client info property + * may be null if the property has not been set and does not have a + * default value. + *

+ * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @return A Properties object that contains the name and current value of + * each of the client info properties supported by the driver. + *

+ * @throws SQLException if the database server returns an error when + * fetching the client info values from the database + */ + public Properties getClientInfo() throws SQLException + { + validateConnection(); + return connection_.getClientInfo(); + } + + //@PDA jdbc40 + /** + * Constructs an object that implements the Clob interface. The object + * returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of + * the Clob interface may be used to add data to the Clob. + * @return An object that implements the Clob interface + * @throws SQLException if an object that implements the + * Clob interface can not be constructed. + * + */ + public Clob createClob() throws SQLException + { + validateConnection(); + return connection_.createClob(); + } + + //@PDA jdbc40 + /** + * Constructs an object that implements the Blob interface. The object + * returned initially contains no data. The setBinaryStream and + * setBytes methods of the Blob interface may be used to add data to + * the Blob. + * @return An object that implements the Blob interface + * @throws SQLException if an object that implements the + * Blob interface can not be constructed + * + */ + public Blob createBlob() throws SQLException + { + validateConnection(); + return connection_.createBlob(); + } + + + + + //@PDA jdbc40 + /** + * Constructs an object that implements the NClob interface. The object + * returned initially contains no data. The setAsciiStream, + * setCharacterStream and setString methods of the NClob interface may + * be used to add data to the NClob. + * @return An object that implements the NClob interface + * @throws SQLException if an object that implements the + * NClob interface can not be constructed. + * + */ +/* ifdef JDBC40 */ + public NClob createNClob() throws SQLException + { + validateConnection(); + return connection_.createNClob(); + } +/* endif */ + + //@PDA jdbc40 + /** + * Constructs an object that implements the SQLXML interface. The object + * returned initially contains no data. The createXmlStreamWriter object and + * setString method of the SQLXML interface may be used to add data to the SQLXML + * object. + * @return An object that implements the SQLXML interface + * @throws SQLException if an object that implements the SQLXML interface can not + * be constructed + */ +/* ifdef JDBC40 */ + public SQLXML createSQLXML() throws SQLException + { + validateConnection(); + return connection_.createSQLXML(); + } +/* endif */ + + //@PDA jdbc40 + /** + * Factory method for creating Array objects. + * + * @param typeName the SQL name of the type the elements of the array map to. The typeName is a + * database-specific name which may be the name of a built-in type, a user-defined type or a standard SQL type supported by this database. This + * is the value returned by Array.getBaseTypeName + * @param elements the elements that populate the returned object + * @return an Array object whose elements map to the specified SQL type + * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + */ + public Array createArrayOf(String typeName, Object[] elements) throws SQLException + { + validateConnection(); + return connection_.createArrayOf(typeName, elements); + } + + //@PDA jdbc40 + /** + * Factory method for creating Struct objects. + * + * @param typeName the SQL type name of the SQL structured type that this Struct + * object maps to. The typeName is the name of a user-defined type that + * has been defined for this database. It is the value returned by + * Struct.getSQLTypeName. + * @param attributes the attributes that populate the returned object + * @return a Struct object that maps to the given SQL type and is populated with the given attributes + * @throws SQLException if a database error occurs, the typeName is null or this method is called on a closed connection + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this data type + */ + public Struct createStruct(String typeName, Object[] attributes) throws SQLException + { + validateConnection(); + return connection_.createStruct(typeName, attributes); + } + + + //@PDA 550 client info + /** + * Sets the value of the client info property specified by name to the + * value specified by value. + *

+ * Applications may use the DatabaseMetaData.getClientInfoProperties + * method to determine the client info properties supported by the driver + * and the maximum length that may be specified for each property. + *

+ * The driver stores the value specified in a suitable location in the + * database. For example in a special register, session parameter, or + * system table column. For efficiency the driver may defer setting the + * value in the database until the next time a statement is executed or + * prepared. Other than storing the client information in the appropriate + * place in the database, these methods shall not alter the behavior of + * the connection in anyway. The values supplied to these methods are + * used for accounting, diagnostics and debugging purposes only. + *

+ * The driver shall generate a warning if the client info name specified + * is not recognized by the driver. + *

+ * If the value specified to this method is greater than the maximum + * length for the property the driver may either truncate the value and + * generate a warning or generate a SQLException. If the driver + * generates a SQLException, the value specified was not set on the + * connection. + *

+ * The following client info properties are supported in Toobox for Java. + *

+ *

+ *

+ * @param name The name of the client info property to set + * @param value The value to set the client info property to. If the + * value is null, the current value of the specified + * property is cleared. + *

+ * @throws SQLException if the database server returns an error while + * setting the client info value on the database server. + *

+ */ + public void setClientInfo(String name, String value) +/* ifdef JDBC40 */ + throws SQLClientInfoException +/* endif */ +/* ifndef JDBC40 + throws SQLException + endif */ + { +/* ifdef JDBC40 */ + try { +/* endif */ + validateConnection(); +/* ifdef JDBC40 */ + }catch(SQLException e) + { + SQLClientInfoException clientIE = new SQLClientInfoException(e.getMessage(), e.getSQLState(), null); + throw clientIE; + } +/* endif */ + + connection_.setClientInfo(name, value); + } + + //@2KRA + /** + * Starts or stops the Database Host Server trace for this connection. + * Note: This method is only supported when running to i5/OS V5R3 or later + * and is ignored if you specified to turn on database host server tracingfs + * using the 'server trace' connection property. + * @param trace true to start database host server tracing, false to end it. + */ + public void setDBHostServerTrace(boolean trace) throws SQLException { //@pdc +/* ifdef JDBC40 */ + try { +/* endif */ + validateConnection(); +/* ifdef JDBC40 */ + }catch(SQLException e) + { + SQLClientInfoException clientIE = new SQLClientInfoException(e.getMessage(), e.getSQLState(), null); + throw clientIE; + } +/* endif */ + connection_.setDBHostServerTrace(trace); + } + + +/* ifdef JDBC40 */ + public void abort(Executor executor) throws SQLException { + validateConnection(); + connection_.abort(executor); + } +/* endif */ + + + +/* ifdef JDBC40 */ + public int getNetworkTimeout() throws SQLException { + validateConnection(); + return connection_.getNetworkTimeout(); + } +/* endif */ + + + + public String getSchema() throws SQLException { + validateConnection(); + return connection_.getSchema(); + } + + +/* ifdef JDBC40 */ + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException { + validateConnection(); + connection_.setNetworkTimeout(executor, milliseconds); + + } +/* endif */ + + + public void setSchema(String schema) throws SQLException { + validateConnection(); + connection_.setSchema(schema); + } + + +} diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCConnectionPoolDataSource.java b/jdbc40/com/ibm/as400/access/AS400JDBCConnectionPoolDataSource.java new file mode 100644 index 000000000..0c727ef6a --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCConnectionPoolDataSource.java @@ -0,0 +1,444 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCConnectionPoolDataSource.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.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.sql.SQLException; +import javax.naming.*; +import javax.sql.ConnectionPoolDataSource; +import javax.sql.PooledConnection; + +/** +* The AS400JDBCConnectionPoolDataSource class represents a factory for +* AS400PooledConnection objects. +* +*

+* The following is an example that creates an AS400JDBCConnectionPoolDataSource object +* that can be used to cache JDBC connections. +* +*

+* // Create a data source for making the connection. +* AS400JDBCConnectionPoolDataSource dataSource = new AS400JDBCConnectionPoolDataSource("myAS400"); +* datasource.setUser("myUser"); +* datasource.setPassword("MYPWD"); +* +* // Get the PooledConnection. +* PooledConnection pooledConnection = datasource.getPooledConnection(); +*
+**/ +public class AS400JDBCConnectionPoolDataSource extends AS400JDBCDataSource implements ConnectionPoolDataSource, Referenceable, Serializable +{ + static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others."; + + static final long serialVersionUID = 4L; + + //@B2D private transient AS400JDBCConnectionPool connectionPool_; //@A2A + + //@B2D private int initialPoolSize_ = 0; //@B0A + //@B2D private int maxIdleTime_ = 3600; //@B0A + //@B2D private int maxPoolSize_ = 0; //@B0A + //@B2D //private int maxStatements_ = 0; //@B0A - Ignore. Use package caching instead. + //@B2D private int minPoolSize_ = 0; //@B0A + //@B2D private int propertyCycle_ = 300; //@B0A + + /** + * Constructs a default AS400JDBCConnectionPoolDataSource object. + **/ + public AS400JDBCConnectionPoolDataSource() + { + super(); + //@B2D initializeTransient(); //@A2A + } + + /** + * Constructs an AS400JDBCConnectionPoolDataSource with the specified serverName. + * @param serverName The IBM i system name. + **/ + public AS400JDBCConnectionPoolDataSource(String serverName) + { + super(serverName); + //@B2D initializeTransient(); //@A2A + } + + /** + * Constructs an AS400JDBCConnectionPoolDataSource with the specified signon information. + * @param serverName The IBM i system name. + * @param user The user id. + * @param password The password. + **/ + public AS400JDBCConnectionPoolDataSource(String serverName, String user, String password) + { + super(serverName, user, password); + //@B2D initializeTransient(); //@A2A + } + + //@A1A + /** + * Constructs an AS400JDBCConnectionPoolDataSource with the specified signon information + * to use for SSL communications with the system. + * @param serverName The IBM i system name. + * @param user The user id. + * @param password The password. + * @param keyRingName The key ring class name to be used for SSL communications with the system. + * @param keyRingPassword The password for the key ring class to be used for SSL communications with the system. + **/ + public AS400JDBCConnectionPoolDataSource(String serverName, String user, String password, + String keyRingName, String keyRingPassword) + { + super(serverName, user, password, keyRingName, keyRingPassword); + //@B2D initializeTransient(); //@A2A + } + + // @F0A - added the following constructor to avoid some object construction + /** + * Constructs an AS400JDBCConnectionPoolDataSource from the specified Reference + * @param reference to retrieve DataSource properties from + **/ + AS400JDBCConnectionPoolDataSource(Reference reference) { + super(reference); + } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Returns the number of connections this pool contains when it is created. + //@B2D * @return The number of pooled connections. The default value is 0. + //@B2D **/ + //@B2D public int getInitialPoolSize() + //@B2D { + //@B2D return initialPoolSize_; + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Returns the maximum amount of time (in seconds) that a pooled + //@B2D * connection in this pool is allowed to remain idle before it is + //@B2D * automatically closed. A value of 0 indicates pooled connections + //@B2D * are never automatically closed. + //@B2D * @return The maximum idle time for a pooled connection in seconds. + //@B2D * The default value is 1 hour (3600 seconds). + //@B2D **/ + //@B2D public int getMaxIdleTime() + //@B2D { + //@B2D return maxIdleTime_; + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Returns the maximum number of connections this connection pool + //@B2D * contains. A value of 0 indicates there is no maximum. + //@B2D * @return The maximum number of connections in the pool. The default + //@B2D * value is 0 (no maximum). + //@B2D **/ + //@B2D public int getMaxPoolSize() + //@B2D { + //@B2D return maxPoolSize_; + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Returns the maximum number of statements this connection pool + //@B2D * should keep open. A value of 0 indicates that no statements + //@B2D * will be cached. + //@B2D * @return The maximum number of cached open statements. The default + //@B2D * value is 0 (no caching). + //@B2D **/ + //@B2D // Note: We don't support statement caching this way. + //@B2D // That's what package caching is for. + //@B2D // public int getMaxStatements() + //@B2D // { + //@B2D // return maxStatements_; + //@B2D // } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Returns the minimum number of connections this connection pool + //@B2D * contains. A value of 0 indicates there is no minimum and connections + //@B2D * are created as they are needed. + //@B2D * @return The minimum number of available connections in the pool. The + //@B2D * default value is 0. + //@B2D **/ + //@B2D public int getMinPoolSize() + //@B2D { + //@B2D return minPoolSize_; + //@B2D } + + + /** + * Returns a pooled connection that is connected to the IBM i system. + * @return A pooled connection. + * @exception SQLException If a database error occurs. + **/ + public PooledConnection getPooledConnection() throws SQLException + { + PooledConnection pc = new AS400JDBCPooledConnection(getConnection()); + + log("PooledConnection created"); + return pc; + + //@B2D //Get a connection from the connection pool. + //@B2D PooledConnection pc = null; //@A2A + //@B2D try + //@B2D { //@A2A + //@B2D connect(); //@B0A + //@B2D pc = connectionPool_.getPooledConnection(); //@A2C + //@B2D + //@B2D log("PooledConnection created"); + //@B2D return pc; + //@B2D } + //@B2D catch (ConnectionPoolException cpe) //@A2A + //@B2D { + //@B2D //@A2A + //@B2D JDError.throwSQLException (JDError.EXC_INTERNAL, cpe); //@A2A + //@B2D } + //@B2D return pc; //@A2M + } + + /** + * Returns a pooled connection that is connected to the IBM i system. + * @param user The userid for the connection. + * @param password The password for the connection. + * @return A pooled connection. + * @exception SQLException If a database error occurs. + **/ + public PooledConnection getPooledConnection(String user, String password) throws SQLException + { + PooledConnection pc = new AS400JDBCPooledConnection(getConnection(user,password)); + + log("PooledConnection created"); + return pc; + + //@B2D PooledConnection pc = null; //@A2A + //@B2D try + //@B2D { //@A2A + //@B2D connect(); //@B0A + //@B2D // Set user and password if user has not been set in the datasource yet. + //@B2D if (getUser().equals("")) //@A2A + //@B2D { + //@B2D //@A2A + //@B2D setUser(user); //@A2A + //@B2D setPassword(password); //@A2A + //@B2D } //@A2A + //@B2D // If the user specified is not equal to the user of the datasource, + //@B2D // throw an ExtendedIllegalStateException. + //@B2D user = user.toUpperCase(); //@A2A + //@B2D if (!(getUser().equals(user))) //@A2A + //@B2D { + //@B2D //@A2A + //@B2D Trace.log(Trace.ERROR, "User in data source already set."); //@A2A + //@B2D throw new ExtendedIllegalStateException("user", ExtendedIllegalStateException.PROPERTY_NOT_CHANGED); //@A2A + //@B2D } //@A2A + //@B2D pc = connectionPool_.getPooledConnection(); //@A2C + //@B2D + //@B2D log("PooledConnection created"); + //@B2D } + //@B2D catch (ConnectionPoolException cpe) //@A2A + //@B2D { + //@B2D //@A2A + //@B2D JDError.throwSQLException (JDError.EXC_INTERNAL, cpe); //@A2A + //@B2D } + //@B2D return pc; //@A2M + } + + + //@B2D //@B0A - Is it OK to have a maintenance thread according to the EJB spec? + //@B2D // Don't we have to run without creating additional threads? + //@B2D /** + //@B2D * Returns the interval (in seconds) between runs of this pool's + //@B2D * maintenance thread. The maintenance thread enforces this pool's + //@B2D * connections and statements so that they conform to the specified + //@B2D * minimum and maximum pool sizes, idle time, and maximum number of + //@B2D * open statements. + //@B2D * @return The number of seconds that this pool should wait before enforcing + //@B2D * its properties. The default value is 5 minutes (300 seconds). + //@B2D **/ + //@B2D public int getPropertyCycle() + //@B2D { + //@B2D return propertyCycle_; + //@B2D } + + + /** + * Returns the Reference object for the data source object. + * This is used by JNDI when bound in a JNDI naming service. + * Contains the information necessary to reconstruct the data source + * object when it is later retrieved from JNDI via an object factory. + * + * @return A Reference object for the data source object. + * @exception NamingException If a naming error occurs resolving the object. + **/ + public Reference getReference() throws NamingException + { + Reference ref = new Reference(this.getClass().getName(), + "com.ibm.as400.access.AS400JDBCObjectFactory", + null); + + Reference dsRef = super.getReference(); + for (int i=0; i< dsRef.size(); i++) + ref.add( dsRef.get(i) ); + + return ref; + } + + + //@B2D //@A2A + //@B2D /** + //@B2D * Initializes the transient data for object de-serialization. + //@B2D **/ + //@B2D private void initializeTransient() + //@B2D { + //@B2D connectionPool_ = new AS400JDBCConnectionPool(this); + //@B2D } + + + /** + * Deserializes and initializes transient data. + **/ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + //@B2D initializeTransient(); //@A2A + } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Sets the number of connections this pool contains when it is created. + //@B2D * @param initialPoolSize The number of pooled connections. Valid values + //@B2D * are 0 or greater. + //@B2D **/ + //@B2D public void setInitialPoolSize(int initialPoolSize) + //@B2D { + //@B2D String property = "initialPoolSize"; + //@B2D if (initialPoolSize < 0) + //@B2D { + //@B2D throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID); + //@B2D } + //@B2D if (!connected_) + //@B2D { + //@B2D Integer old = new Integer(initialPoolSize_); + //@B2D initialPoolSize_ = initialPoolSize; + //@B2D changes_.firePropertyChange(property, old, new Integer(initialPoolSize_)); + //@B2D } + //@B2D else + //@B2D { + //@B2D throw new ExtendedIllegalStateException(property, ExtendedIllegalStateException.PROPERTY_NOT_CHANGED); + //@B2D } + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Sets the maximum amount of time (in seconds) that a pooled + //@B2D * connection in this pool is allowed to remain idle before it is + //@B2D * automatically closed. A value of 0 indicates pooled connections + //@B2D * are never automatically closed. + //@B2D * @param maxIdleTime The maximum idle time for a pooled connection in seconds. + //@B2D * Valid values are 0 or greater. + //@B2D **/ + //@B2D public void setMaxIdleTime(int maxIdleTime) + //@B2D { + //@B2D String property = "maxIdleTime"; + //@B2D Integer old = new Integer(maxIdleTime_); + //@B2D maxIdleTime_ = maxIdleTime; + //@B2D changes_.firePropertyChange(property, old, new Integer(maxIdleTime_)); + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Sets the maximum number of connections this connection pool + //@B2D * contains. A value of 0 indicates there is no maximum. + //@B2D * @param maxPoolSize The maximum number of connections in this pool. + //@B2D * Valid values are 0 or greater. + //@B2D **/ + //@B2D public void setMaxPoolSize(int maxPoolSize) + //@B2D { + //@B2D String property = "maxPoolSize"; + //@B2D Integer old = new Integer(maxPoolSize_); + //@B2D maxPoolSize_ = maxPoolSize; + //@B2D changes_.firePropertyChange(property, old, new Integer(maxPoolSize_)); + //@B2D } + + + //@B2D //@B0A + //@B2D /** + //@B2D * Sets the maximum number of statements this connection pool + //@B2D * should keep open. A value of 0 indicates that no statements + //@B2D * will be cached. + //@B2D * @param maxStatements The maximum number of cached open statements. + //@B2D * Valid values are 0 or greater. + //@B2D **/ + //@B2D // Note: Use package caching to get statement caching. + //@B2D /* public void setMaxStatements(int maxStatements) + //@B2D { + //@B2D String property = "maxStatements"; + //@B2D Integer old = new Integer(maxStatements_); + //@B2D maxStatements_ = maxStatements; + //@B2D changes_.firePropertyChange(property, old, new Integer(maxStatements_)); + //@B2D } + //@B2D */ + + + //@B2D //@B0A + //@B2D /** + //@B2D * Sets the minimum number of connections this connection pool + //@B2D * contains. A value of 0 indicates there is no minimum and connections + //@B2D * are created as they are needed. + //@B2D * @param minPoolSize The minimum number of available connections in the pool. + //@B2D * Valid values are 0 or greater. + //@B2D **/ + //@B2D public void setMinPoolSize(int minPoolSize) + //@B2D { + //@B2D String property = "minPoolSize"; + //@B2D Integer old = new Integer(minPoolSize_); + //@B2D minPoolSize_ = minPoolSize; + //@B2D changes_.firePropertyChange(property, old, new Integer(minPoolSize_)); + //@B2D } + + + //@B2D //@B0A - Is it OK to have a maintenance thread according to the EJB spec? + //@B2D // Don't we have to run without creating additional threads? + //@B2D /** + //@B2D * Sets the interval (in seconds) between runs of this pool's + //@B2D * maintenance thread. The maintenance thread enforces this pool's + //@B2D * connections and statements so that they conform to the specified + //@B2D * minimum and maximum pool sizes, idle time, and maximum number of + //@B2D * open statements. A value of 0 indicates that a maintenance thread + //@B2D * should not be created. + //@B2D * @param The number of seconds that this pool should wait before enforcing + //@B2D * its properties. Valid values are 0 or greater. + //@B2D **/ + //@B2D public void setPropertyCycle(int propertyCycle) + //@B2D { + //@B2D String property = "propertyCycle"; + //@B2D Integer old = new Integer(propertyCycle_); + //@B2D propertyCycle_ = propertyCycle; + //@B2D changes_.firePropertyChange(property, old, new Integer(propertyCycle_)); + //@B2D } + + + //@pda jdbc40 + protected String[] getValidWrappedList() + { + return new String[] { "com.ibm.as400.access.AS400JDBCConnectionPoolDataSource", "java.sql.ConnectionPoolDataSource" }; + } +} + diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCDataSource.java b/jdbc40/com/ibm/as400/access/AS400JDBCDataSource.java new file mode 100644 index 000000000..3c1d9cfce --- /dev/null +++ b/jdbc40/com/ibm/as400/access/AS400JDBCDataSource.java @@ -0,0 +1,5308 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// JTOpen (IBM Toolbox for Java - OSS version) +// +// Filename: AS400JDBCDataSource.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.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyVetoException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.sql.Connection; +import java.sql.DriverPropertyInfo; +import java.sql.SQLException; +/* ifdef JDBC40 */ +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; +/* endif */ +import java.util.Enumeration; +import java.util.Properties; +import java.util.Random; // @J3a + +import javax.sql.DataSource; // JDBC2.0 std-ext +import javax.naming.NamingException; // JNDI +import javax.naming.Reference; // JNDI +import javax.naming.Referenceable; // JNDI +import javax.naming.StringRefAddr; // JNDI + +/** +* The AS400JDBCDataSource class represents a factory for IBM i database connections. +* +*

The following is an example that creates an AS400JDBCDataSource object and creates a +* connection to the database. +* +*

+* // Create a data source for making the connection. +* AS400JDBCDataSource datasource = new AS400JDBCDataSource("myAS400"); +* datasource.setUser("myUser"); +* datasource.setPassword("MYPWD"); + +* // Create a database connection to the system. +* Connection connection = datasource.getConnection(); +*
+* +*

The following example registers an AS400JDBCDataSource object with JNDI and then +* uses the object returned from JNDI to obtain a database connection. +*

+* // Create a data source to the IBM i database. +* AS400JDBCDataSource dataSource = new AS400JDBCDataSource(); +* dataSource.setServerName("myAS400"); +* +* // Register the datasource with the Java Naming and Directory Interface (JNDI). +* Hashtable env = new Hashtable(); +* env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); +* Context context = new InitialContext(env); +* context.bind("jdbc/customer", dataSource); +* +* // Return an AS400JDBCDataSource object from JNDI and get a connection. +* AS400JDBCDataSource datasource = (AS400JDBCDataSource) context.lookup("jdbc/customer"); +* Connection connection = datasource.getConnection("myUser", "MYPWD"); +*
+**/ +public class AS400JDBCDataSource +/* ifdef JDBC40 */ +extends ToolboxWrapper +/* endif */ + +implements DataSource, Referenceable, Serializable, Cloneable //@PDC 550 +{ + static final long serialVersionUID = 4L; + + + + /** + * Implementation notes: + * The properties listed in com.ibm.as400.access.JDProperties should also be included here. + **/ + + // Constants + private static final String DATABASE_NAME = "databaseName"; + private static final String DATASOURCE_NAME = "dataSourceName"; + private static final String DESCRIPTION = "description"; + private static final String SERVER_NAME = "serverName"; + private static final String USER = "userName"; + private static final String KEY_RING_NAME = "keyring"; // @F0A + private static final String PASSWORD = "pw"; // @F0A + private static final String KEY_RING_PASSWORD = "keyringpw"; // @F0A + private static final String SECURE = "secure"; // @F0A + private static final String SAVE_PASSWORD = "savepw"; // @F0A + private static final String PLAIN_TEXT_PASSWORD = "pwd"; //@K1A + private static final String TRUE_ = "true"; + private static final String FALSE_ = "false"; + private static final String TOOLBOX_DRIVER = "jdbc:as400:"; + private static final int MAX_THRESHOLD = 16777216; // Maximum threshold (bytes). @A3C, @A4A + static final int MAX_SCALE = 63; // Maximum decimal scale + + // socket options to store away in JNDI + private static final String SOCKET_KEEP_ALIVE = "soKeepAlive"; // @F1A + private static final String SOCKET_RECEIVE_BUFFER_SIZE = "soReceiveBufferSize"; // @F1A + private static final String SOCKET_SEND_BUFFER_SIZE = "soSendBufferSize"; // @F1A + private static final String SOCKET_LINGER = "soLinger"; // @F1A + private static final String SOCKET_TIMEOUT = "soTimeout"; // @F1A + private static final String SOCKET_LOGIN_TIMEOUT = "loginTimeout"; // @st3 + private static final String SOCKET_TCP_NO_DELAY = "soTCPNoDelay"; // @F1A + + // Data source properties. + transient private AS400 as400_; // AS400 object used to store and encrypt the password. + // @J2d private String databaseName_ = ""; // Database name. @A6C + private String dataSourceName_ = ""; // Data source name. @A6C + private String description_ = ""; // Data source description. @A6C + private JDProperties properties_; // IBM i connection properties. + private SocketProperties sockProps_; // IBM i socket properties @F1A + transient private PrintWriter writer_; // The EventLog print writer. @C7c + transient private EventLog log_; //@C7c + + private String serialServerName_; // system name used in serialization. + private String serialUserName_; // User used in serialization. + private String serialKeyRingName_; //@B4A // Key ring name used in serialization. + transient PropertyChangeSupport changes_; //@B0C + private boolean isSecure_ = false; //@B4A + + // Handles loading the appropriate resource bundle + // private static ResourceBundleLoader loader_; //@A9A + + + // In mod 5 support was added to optionally serialize the password with the + // rest of the properties. By default this is off. setSavePasswordWhenSerialized(true) + // must be called to save the password. By calling this the application takes + // responsibility for protecting the serialized bytes. The password is not saved in the + // clear. The password string is confused so that something more than just looking at the + // serialized bytes must be done to see the password. + private char[] serialPWBytes_ = null; //@J3a + private char[] serialKeyRingPWBytes_ = null; //@J3a + private boolean savePasswordWhenSerialized_ = false; //@J3a by default, don't save password!!!! + + /** + * The maximum storage space in megabytes, that can be used to execute a query. + **/ + public static final int MAX_STORAGE_LIMIT = 2147352578; // Maximum query storage limit @550 + + + /** + Start tracing the JDBC client. This is the same as setting + property "trace=true"; Note the constant is not public. + It is defined only to be compatible with ODBC + The numeric value of this constant is 1. + **/ + static final int TRACE_CLIENT = 1; // @j1a + + /** + Start the database monitor on the JDBC server job. + This constant is used when setting the level of tracing for the JDBC server job. + The numeric value of this constant is 2. + **/ + public static final int SERVER_TRACE_START_DATABASE_MONITOR = 2; // @j1a + + /** + Start debug on the JDBC server job. + This constant is used when setting the level of tracing for the JDBC server job. + The numeric value of this constant is 4. + **/ + public static final int SERVER_TRACE_DEBUG_SERVER_JOB = 4; // @j1a + + /** + Save the joblog when the JDBC server job ends. + This constant is used when setting the level of tracing for the JDBC server job. + The numeric value of this constant is 8. + **/ + public static final int SERVER_TRACE_SAVE_SERVER_JOBLOG = 8; // @j1a + + /** + Start job trace on the JDBC server job. + This constant is used when setting the level of tracing for the JDBC server job. + The numeric value of this constant is 16. + **/ + public static final int SERVER_TRACE_TRACE_SERVER_JOB = 16; // @j1a + + /** + Save SQL information. + This constant is used when setting the level of tracing for the JDBC server job. + The numeric value of this constant is 32. + **/ + public static final int SERVER_TRACE_SAVE_SQL_INFORMATION = 32; // @j1a + + + //@cc1 + /** + * CONCURRENTACCESS_NOT_SET - Indicates that currently committed behavior is not + * requested explicitly by the client. + */ + public final static int CONCURRENTACCESS_NOT_SET = 0; + //@cc1 + /** + * CONCURRENTACCESS_USE_CURRENTLY_COMMITTED - Indicates that the currently committed + * behavior is requested at the server. + */ + public final static int CONCURRENTACCESS_USE_CURRENTLY_COMMITTED = 1; + //@cc1 + /** + * CONCURRENTACCESS_WAIT_FOR_OUTCOME - Indicates that the readers will + * wait on the writers during lock contention. + */ + public final static int CONCURRENTACCESS_WAIT_FOR_OUTCOME = 2; + //@cc1 + /** + * CONCURRENTACCESS_SKIP_LOCKS - Indicates that the readers will + * skip locks. + */ + public final static int CONCURRENTACCESS_SKIP_LOCKS = 3; + + + /** + * Constructs a default AS400JDBCDataSource object. + **/ + public AS400JDBCDataSource() + { + initializeTransient(); + properties_ = new JDProperties(null, null); + sockProps_ = new SocketProperties(); + } + + /** + * Constructs an AS400JDBCDataSource object to the specified serverName. + * @param serverName The name of the IBM i system. + **/ + public AS400JDBCDataSource(String serverName) + { + this(); + + setServerName(serverName); + } + + /** + * Constructs an AS400JDBCDataSource object with the specified signon information. + * @param serverName The name of the IBM i system. + * @param user The user id. + * @param password The user password. + **/ + public AS400JDBCDataSource(String serverName, String user, String password) + { + this(); + + setServerName(serverName); + setUser(user); + setPassword(password); + } + + //@K1A + /** + * Constructs an AS400JDBCDataSource object with the specified AS400 object + * @param as400 The AS400 object + **/ + public AS400JDBCDataSource(AS400 as400) + { + this(); + + as400_ = as400; + if( as400 instanceof SecureAS400 ) + setSecure(true); + + } + + //@B4A + /** + * Constructs an AS400JDBCDataSource object with the specified signon information + * to use for SSL communications with the system. + * @param serverName The name of the IBM i system. + * @param user The user id. + * @param password The user password. + * @param keyRingName The key ring class name to be used for SSL communications with the system. + * @param keyRingPassword The password for the key ring class to be used for SSL communications with the system. + **/ + public AS400JDBCDataSource(String serverName, String user, String password, + String keyRingName, String keyRingPassword) + { + this(); + + setSecure(true); // @F0M + + try + { + as400_ = new SecureAS400(as400_); + ((SecureAS400)as400_).setKeyRingName(keyRingName, keyRingPassword); + } + catch (PropertyVetoException pe) + { /* will never happen */ + } + serialKeyRingName_ = keyRingName; + + // @J3 There is no get/set keyring name / password methods so they really aren't bean + // properties, but in v5r1 the keyring name is saved as if it is a property. Since + // the code saved the name we will also save the password. + serialKeyRingPWBytes_ = xpwConfuse(keyRingPassword); //@J3a // @F0M (changed from keyRingName to keyRingPassword) + + setServerName(serverName); + setUser(user); + setPassword(password); + } + + // @F0A - Added the following constructor to avoid creating some extra objects + /** + * Constructs an AS400JDBCDataSource object from the specified Reference object + * @param reference to retrieve the DataSource properties from + **/ + AS400JDBCDataSource(Reference reference) { + /* + * Implementation note: This method is called from AS400JDBCObjectFactory.getObjectInstance + */ + + // check to make sure our reference is not null + if (reference == null) + throw new NullPointerException("reference"); + + // set up property change support + changes_ = new PropertyChangeSupport(this); + + // set up the as400 object + if (((String)reference.get(SECURE).getContent()).equalsIgnoreCase(TRUE_)) { + isSecure_ = true; + as400_ = new SecureAS400(); + + // since the as400 object is secure, get the key ring info + serialKeyRingName_ = (String)reference.get(KEY_RING_NAME).getContent(); + if (reference.get(KEY_RING_PASSWORD) != null) + serialKeyRingPWBytes_ = ((String)reference.get(KEY_RING_PASSWORD).getContent()).toCharArray(); + else + serialKeyRingPWBytes_ = null; + + try { + if (serialKeyRingPWBytes_ != null && serialKeyRingPWBytes_.length > 0) + ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_, xpwDeconfuse(serialKeyRingPWBytes_)); + else + ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_); + } catch (PropertyVetoException pve) { /* Will never happen */ } + + } else { + isSecure_ = false; + as400_ = new AS400(); + } + + // must initialize the JDProperties so the property change checks dont get a NullPointerException + properties_ = new JDProperties(null, null); + + Properties properties = new Properties(); + sockProps_ = new SocketProperties(); + + Enumeration list = reference.getAll(); + while (list.hasMoreElements()) + { + StringRefAddr refAddr = (StringRefAddr)list.nextElement(); + String property = refAddr.getType(); + String value = (String)reference.get(property).getContent(); + + // constant identifiers were used to store in JNDI + // all of these were handled already so do not put them in the properties + if (property.equals(DATABASE_NAME)) + setDatabaseName(value); + else if (property.equals(DATASOURCE_NAME)) + setDataSourceName(value); + else if (property.equals(DESCRIPTION)) + setDescription(value); + else if (property.equals(SERVER_NAME)) + setServerName(value); + else if (property.equals(USER)) + setUser(value); + else if(property.equals(PLAIN_TEXT_PASSWORD)) { //@K1A + //set the password //@K1A + setPassword(value); //@K1A + } + else if (property.equals(PASSWORD)) { + if(reference.get(PLAIN_TEXT_PASSWORD) != null) //@K1A + { //@K1A + setPassword((String)reference.get(PLAIN_TEXT_PASSWORD).getContent()); //@K1A + } //@K1A + else //@K1A + { //@K1A + // get the password back from the serialized char[] + serialPWBytes_ = value.toCharArray(); + // decode the password and set it on the as400 + as400_.setPassword(xpwDeconfuse(serialPWBytes_)); + } //@K1A + } + else if (property.equals(SAVE_PASSWORD)) { + // set the savePasswordWhenSerialized_ flag + savePasswordWhenSerialized_ = value.equals(TRUE_) ? true : false; + } else if (property.equals(SECURE) || property.equals(KEY_RING_NAME) || property.equals(KEY_RING_PASSWORD)) { + // do nothing for these keys, they have already been handled + } + else if (property.equals(SOCKET_KEEP_ALIVE)) { + sockProps_.setKeepAlive((value.equals(TRUE_)? true : false)); + } + else if (property.equals(SOCKET_RECEIVE_BUFFER_SIZE)) { + sockProps_.setReceiveBufferSize(Integer.parseInt(value)); + } + else if (property.equals(SOCKET_SEND_BUFFER_SIZE)) { + sockProps_.setSendBufferSize(Integer.parseInt(value)); + } + else if (property.equals(SOCKET_LINGER)) { + sockProps_.setSoLinger(Integer.parseInt(value)); + } + else if (property.equals(SOCKET_TIMEOUT)) { + sockProps_.setSoTimeout(Integer.parseInt(value)); + } + else if (property.equals(SOCKET_LOGIN_TIMEOUT)) { //@st3 + sockProps_.setLoginTimeout(Integer.parseInt(value)); //@st3 + } + else if (property.equals(SOCKET_TCP_NO_DELAY)) { + sockProps_.setTcpNoDelay((value.equals(TRUE_)? true : false)); + } + else + { + properties.put(property, value); + } + } + properties_ = new JDProperties(properties, null); + + // get the prompt property and set it back in the as400 object + String prmpt = properties_.getString(JDProperties.PROMPT); + if (prmpt != null && prmpt.equalsIgnoreCase(FALSE_)) + setPrompt(false); + else if (prmpt != null && prmpt.equalsIgnoreCase(TRUE_)) + setPrompt(true); + + } + + /** + * Adds a PropertyChangeListener. The specified PropertyChangeListener's + * propertyChange method is called each time the value of any bound + * property is changed. + * @see #removePropertyChangeListener + * @param listener The PropertyChangeListener. + **/ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + if (listener == null) + throw new NullPointerException("listener"); + changes_.addPropertyChangeListener(listener); + + as400_.addPropertyChangeListener(listener); + } + + //@PDA 550 - clone + /** + * Method to create a clone of AS400JDBCDataSource. This does a shallow + * copy, with the exception of JDProperties, which also gets cloned. + */ + public Object clone() + { + try + { + Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.close()"); + AS400JDBCDataSource clone = (AS400JDBCDataSource) super.clone(); + clone.properties_ = (JDProperties) this.properties_.clone(); + return clone; + } catch (CloneNotSupportedException e) + { // This should never happen. + Trace.log(Trace.ERROR, e); + throw new UnsupportedOperationException("clone()"); + } + } + + /** + * Returns the level of database access for the connection. + * @return The access level. Valid values include: "all" (all SQL statements allowed), + * "read call" (SELECT and CALL statements allowed), and "read only" (SELECT statements only). + * The default value is "all". + **/ + public String getAccess() + { + return properties_.getString(JDProperties.ACCESS); + } + + // @C9 new method + /** + * Returns what behaviors of the Toolbox JDBC driver have been overridden. + * Multiple behaviors can be overridden in combination by adding + * the constants and passing that sum on the setBehaviorOverride() method. + * @return The behaviors that have been overridden. + *

The return value is a combination of the following: + *

+ * + **/ + public int getBehaviorOverride() + { + return properties_.getInt(JDProperties.BEHAVIOR_OVERRIDE); + } + + //@B2A + /** + * Returns the output string type of bidi data. See + * BidiStringType for more information and valid values. -1 will be returned + * if the value has not been set. + **/ + public int getBidiStringType() //@B3C + { + String value = properties_.getString(JDProperties.BIDI_STRING_TYPE); //@B3C + try + { //@B3A //@B3A + return Integer.parseInt (value); //@B3A + } //@B3A + catch (NumberFormatException nfe) // if value is "", that is, not set //@B3A + { //@B3A + return -1; //@B3A + } //@B3A + } + + + /** + * Returns the criteria for retrieving data from the system in + * blocks of records. Specifying a non-zero value for this property + * will reduce the frequency of communication to the system, and + * therefore increase performance. + * @return The block criteria. + *

Valid values include: + *

+ **/ + public int getBlockCriteria() + { + return properties_.getInt(JDProperties.BLOCK_CRITERIA); + } + + /** + * Returns the block size in kilobytes to retrieve from the system and + * cache on the client. This property has no effect unless the block criteria + * property is non-zero. Larger block sizes reduce the frequency of + * communication to the system, and therefore may increase performance. + * @return The block size in kilobytes. + *

Valid values include: + *

+ **/ + public int getBlockSize() + { + return properties_.getInt(JDProperties.BLOCK_SIZE); + } + + + /** + * Returns the database connection. + * @return The connection. + * @exception SQLException If a database error occurs. + **/ + public Connection getConnection() throws SQLException + { + //if the object was created with a keyring, or if the user asks for the object + //to be secure, clone a SecureAS400 object; otherwise, clone an AS400 object + if (isSecure_ || isSecure()) //@B4A //@C2C + return getConnection(new SecureAS400(as400_)); //@B4A + else //@B4A + return getConnection(new AS400(as400_)); + } + + + // @J3 Nothing to change here. The password is serialized only when passed on the c'tor + // or via the settors. That is, "bean properties" are affected only when using the + // c'tor specifying system, uid, and pwd, or the settors are used. The bean properties + // are not affected if this method is used, or if the default c'tor is used such + // that our sign-on dialog is used to get system, uid and pwd from the user. + /** + * Returns the database connection using the specified user and password. + * @param user The database user. + * @param password The database password. + * @return The connection + * @exception SQLException If a database error occurs. + **/ + public Connection getConnection(String user, String password) throws SQLException + { + // Validate the parameters. + //@pw3 Add way to get old behavior allowing "" (!but also need to allow new behavior of allowing null is/passwd so customers can slowly migrate) + String secureCurrentUser = SystemProperties.getProperty (SystemProperties.JDBC_SECURE_CURRENT_USER); //@pw3 + boolean isSecureCurrentUser = true; //@pw3 + //if system property or jdbc property is set to false then secure current user code is not used + //null value for system property means not specified...so true by default + if(((secureCurrentUser != null) && (Boolean.valueOf(secureCurrentUser).booleanValue() == false)) || !isSecureCurrentUser()) //@pw3 + isSecureCurrentUser = false; //@pw3 + + boolean forcePrompt = false; //@prompt + + //check if "". + if ("".equals(user)) //@pw1 + { //@pw1 + if(isSecureCurrentUser)//@pw3 + { //@pw3 + if (JDTrace.isTraceOn()) //jdbc category trace //@pw1 + JDTrace.logInformation (this, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1 + //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 + forcePrompt = true; //@prompt + } //@pw3 + } //@pw1 + if ("".equals(password)) //@pw1 + { //@pw1 + if(isSecureCurrentUser)//@pw3 + { //@pw3 + if (JDTrace.isTraceOn()) //jdbc category trace //@pw1 + JDTrace.logInformation (this, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1 + //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 + forcePrompt = true; //@prompt + } //@pw3 + } //@pw1 + + //Next, hack for nulls to work on IBM i + //New security: replace null with "" to mimic old behavior to allow null logons...disallowing "" above. + if (user == null) //@pw1 + user = ""; //@pw1 + if (password == null) //@pw1 + password = ""; //@pw1 + + //check for *current + if (user.compareToIgnoreCase("*CURRENT") == 0) //@pw1 + { //@pw1 + if(isSecureCurrentUser)//@pw3 + { //@pw3 + if (JDTrace.isTraceOn()) //jdbc category trace //@pw1 + JDTrace.logInformation (this, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1 + //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 + forcePrompt = true; //@prompt + } //@pw3 + + } //@pw1 + if (password.compareToIgnoreCase("*CURRENT") == 0) //@pw1 + { //@pw1 + if(isSecureCurrentUser)//@pw3 + { //@pw3 + if (JDTrace.isTraceOn()) //jdbc category trace //@pw1 + JDTrace.logInformation (this, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1 + //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 + forcePrompt = true; //@prompt + } //@pw3 + } //@pw1 + + AS400 as400Object; + + //if the object was created with a keyring, or if the user asks for the object + //to be secure, clone a SecureAS400 object; otherwise, clone an AS400 object + if (isSecure_ || isSecure()) //@C2A + { //@C2A + as400Object = new SecureAS400(getServerName(), user, password); //@C2A + } //@C2A + else + { //@C2A //@C2A + as400Object = new AS400(getServerName(), user, password); //@C2A + } //@C2A + + try //@PDA + { //@PDA + if(!as400_.isThreadUsed()) //@PDA + as400Object.setThreadUsed(false); //true by default //@PDA + } catch (PropertyVetoException pve) //@PDA + { /*ignore*/ //@PDA + } //@PDA + + //set gui available on the new object to false if user turned prompting off + try + { //@C2A + if (!isPrompt()) //@C2A + as400Object.setGuiAvailable(false); //@C2A + } //@C2A + catch (PropertyVetoException pve) //@C2A + { /*ignore*/ //@C2A + } //@C2A + + if(forcePrompt) //@prompt + as400Object.forcePrompt(); //@prompt + + return getConnection(as400Object); //@C2A + + //@C2D return getConnection(new AS400(getServerName(), user, password)); + } + + + /** + * Creates the database connection based on the signon and property information. + * @param as400 The AS400 object used to make the connection. + * @exception SQLException If a database error occurs. + **/ + private Connection getConnection(AS400 as400) throws SQLException + { + // Set the socket properties, if there are any, on the AS400 object before making a connection. + if(sockProps_ != null){ + as400.setSocketProperties(sockProps_); + }else + { + if(JDTrace.isTraceOn()) + JDTrace.logInformation(this, "sockProps_: null"); + } + + AS400JDBCConnection connection = null; + + connection = new AS400JDBCConnection(); + + connection.setSystem(as400); + connection.setProperties(new JDDataSourceURL(TOOLBOX_DRIVER + "//" + as400.getSystemName()), properties_, as400); //@C1C + + log(ResourceBundleLoader.getText("AS400_JDBC_DS_CONN_CREATED")); //@A9C + return connection; + } + + //@cc1 + /** + * This method returns the concurrent access resolution setting. + * This method has no effect on IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @return The concurrent access resolution setting. Possible return valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public int getConcurrentAccessResolution () + { + return properties_.getInt(JDProperties.CONCURRENT_ACCESS_RESOLUTION); + } + + //@C8A + /** + * Returns the value of the cursor sensitivity property. If the resultSetType is + * ResultSet.TYPE_FORWARD_ONLY or ResultSet.TYPE_SCROLL_SENSITIVE, the value of this property + * will control what cursor sensitivity is requested from the database. If the resultSetType + * is ResultSet.TYPE_SCROLL_INSENSITIVE, this property will be ignored. + * @return The cursor sensitivity. + *

Valid values include: + *

+ * The default is "asensitive". + * + * This property is ignored when connecting to systems + * running OS/400 V5R1 and earlier. + **/ + public String getCursorSensitivity() + { + return properties_.getString(JDProperties.CURSOR_SENSITIVITY); + } + + + /** + * Returns the database name property. For more information see + * the documentation for the setDatabaseName() method in this class. + * @return The database name. + **/ + public String getDatabaseName() + { + // @J2d return databaseName_; + return properties_.getString(JDProperties.DATABASE_NAME); // @J2a + } + + /** + * Returns the data source name property. + * This property is used to name an underlying data source when connection pooling is used. + * @return The data source name. + **/ + public String getDataSourceName() + { + return dataSourceName_; + } + + /** + * Returns the IBM i date format used in date literals within SQL statements. + * @return The date format. + *

Valid values include: + *

+ * The default is based on the server job. + **/ + public String getDateFormat() + { + return properties_.getString(JDProperties.DATE_FORMAT); + } + + /** + * Returns the IBM i date separator used in date literals within SQL statements. + * This property has no effect unless the "data format" property is set to: + * "julian", "mdy", "dmy", or "ymd". + * @return The date separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public String getDateSeparator() + { + return properties_.getString(JDProperties.DATE_SEPARATOR); + } + + //@DFA + /** + * Returns the decfloat rounding mode. + * @return The decfloat rounding mode. + *

Valid values include: + *

+ **/ + public String getDecfloatRoundingMode() + { + return properties_.getString(JDProperties.DECFLOAT_ROUNDING_MODE); + } + + /** + * Returns the IBM i decimal separator used in numeric literals within SQL statements. + * @return The decimal separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public String getDecimalSeparator() + { + return properties_.getString(JDProperties.DECIMAL_SEPARATOR); + } + + //@igwrn + /** + * Returns the ignore warnings property. + * Specifies a list of SQL states for which the driver should not create warning objects. + * @return The ignore warnings. + **/ + public String getIgnoreWarnings() + { + return properties_.getString(JDProperties.IGNORE_WARNINGS); + } + + + /** + * Returns the description of the data source. + * @return The description. + **/ + public String getDescription() + { + return description_; + } + + // @A2A + /** + * Returns the JDBC driver implementation. + * This property has no + * effect if the "secondary URL" property is set. + * This property cannot be set to "native" if the + * environment is not an IBM i Java Virtual Machine. + *

Valid values include: + *

+ * The default value is "toolbox". + * Note: Not supported in a connection pool. + **/ + public String getDriver() + { + return properties_.getString(JDProperties.DRIVER); + } + + /** + * Returns the amount of detail for error messages originating from + * the IBM i system. + * @return The error message level. + * Valid values include: "basic" and "full". The default value is "basic". + **/ + public String getErrors() + { + return properties_.getString(JDProperties.ERRORS); + } + + /** + * Returns the IBM i system libraries to add to the server job's library list. + * The libraries are delimited by commas or spaces, and + * "*LIBL" may be used as a place holder for the server job's + * current library list. The library list is used for resolving + * unqualified stored procedure calls and finding schemas in + * DatabaseMetaData catalog methods. If "*LIBL" is not specified, + * the specified libraries will replace the server job's current library list. + * @return The library list. + **/ + public String getLibraries() + { + return properties_.getString(JDProperties.LIBRARIES); + } + + /** + * Returns the maximum LOB (large object) size in bytes that + * can be retrieved as part of a result set. LOBs that are larger + * than this threshold will be retrieved in pieces using extra + * communication to the system. Larger LOB thresholds will reduce + * the frequency of communication to the system, but will download + * more LOB data, even if it is not used. Smaller LOB thresholds may + * increase frequency of communication to the system, but will only + * download LOB data as it is needed. + * @return The lob threshold. Valid range is 0-16777216. + * The default value is 32768. + **/ + public int getLobThreshold() + { + return properties_.getInt(JDProperties.LOB_THRESHOLD); + } + + /** + * Returns the timeout value in seconds. + * Note: This value is not used or supported. + * The timeout value is determined by the IBM i system. + * @return the maximum time in seconds that this data source can wait while attempting to connect to a database. + **/ + public int getLoginTimeout() + { + return properties_.getInt(JDProperties.LOGIN_TIMEOUT); + } + + /** + * Returns the log writer for this data source. + * @return The log writer for this data source. + * @exception SQLException If a database error occurs. + **/ + public PrintWriter getLogWriter() throws SQLException + { + return writer_; + } + + //@PDA + /** + * Indicates how to retrieve DatabaseMetaData. + * If set to 0, database metadata will be retrieved through the ROI data flow. + * If set to 1, database metadata will be retrieved by calling system stored procedures. + * The methods that currently are available through stored procedures are: + * getColumnPrivileges + * @return the metadata setting. + * The default value is 1. + **/ + public int getMetaDataSource() + { + return properties_.getInt(JDProperties.METADATA_SOURCE); + } + + //@dup + /** + * Indicates how to retrieve DatabaseMetaData. + * If set to 0, database metadata will be retrieved through the ROI data flow. + * If set to 1, database metadata will be retrieved by calling system stored procedures. + * The methods that currently are available through stored procedures are: + * getColumnPrivileges + * @return the metadata setting. + * The default value is 1. + * Note: this method is the same as getMetaDataSource() so that it corresponds to the connection property name + **/ + public int getMetadataSource() + { + return getMetaDataSource(); + } + + /** + * Returns the naming convention used when referring to tables. + * @return The naming convention. Valid values include: "sql" (e.g. schema.table) + * and "system" (e.g. schema/table). The default value is "sql". + **/ + public String getNaming() + { + return properties_.getString(JDProperties.NAMING); + } + + /** + * Returns the base name of the SQL package. Note that only the + * first six characters are used to generate the name of the SQL package on the system. + * This property has no effect unless + * the extended dynamic property is set to true. In addition, this property + * must be set if the extended dynamic property is set to true. + * @return The base name of the SQL package. + **/ + public String getPackage() + { + return properties_.getString(JDProperties.PACKAGE); + } + + /** + * Returns the type of SQL statement to be stored in the SQL package. This can + * be useful to improve the performance of complex join conditions. This + * property has no effect unless the extended dynamic property is set to true. + * @return The type of SQL statement. + * Valid values include: "default" (only store SQL statements with parameter + * markers in the package) and "select" (store all SQL SELECT statements + * in the package). The default value is "default". + **/ + public String getPackageCriteria() + { + return properties_.getString(JDProperties.PACKAGE_CRITERIA); + } + + /** + * Returns the action to take when SQL package errors occur. When an SQL package + * error occurs, the driver will optionally throw an SQLException or post a + * warning to the Connection, based on the value of this property. This property + * has no effect unless the extended dynamic property is set to true. + * @return The action to take when SQL errors occur. + * Valid values include: "exception", "warning", and "none". The default value is "warning". + **/ + public String getPackageError() + { + return properties_.getString(JDProperties.PACKAGE_ERROR); + } + /** + * Returns the library for the SQL package. This property has no effect unless + * the extended dynamic property is set to true. + * @return The SQL package library. The default package library is "QGPL". + **/ + public String getPackageLibrary() + { + return properties_.getString(JDProperties.PACKAGE_LIBRARY); + } + + /** + * Returns the name of the proxy server. + * @return The proxy server. + **/ + public String getProxyServer() + { + return properties_.getString(JDProperties.PROXY_SERVER); + } + + /** + * Returns the Reference object for the data source object. + * This is used by JNDI when bound in a JNDI naming service. + * Contains the information necessary to reconstruct the data source + * object when it is later retrieved from JNDI via an object factory. + * + * @return A Reference object of the data source object. + * @exception NamingException If a naming error occurs in resolving the object. + **/ + public Reference getReference() throws NamingException + { + + Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.getReference"); + + Reference ref = new Reference(this.getClass().getName(), + "com.ibm.as400.access.AS400JDBCObjectFactory", + null); + + // Add the JDBC properties. + DriverPropertyInfo[] propertyList = properties_.getInfo(); + for (int i=0; i< propertyList.length; i++) + { + if (propertyList[i].value != null) + ref.add(new StringRefAddr(propertyList[i].name, propertyList[i].value)); + } + + // Add the Socket options + if (sockProps_.keepAliveSet_) ref.add(new StringRefAddr(SOCKET_KEEP_ALIVE, (sockProps_.keepAlive_ ? "true" : "false"))); + if (sockProps_.receiveBufferSizeSet_) ref.add(new StringRefAddr(SOCKET_RECEIVE_BUFFER_SIZE, Integer.toString(sockProps_.receiveBufferSize_))); + if (sockProps_.sendBufferSizeSet_) ref.add(new StringRefAddr(SOCKET_SEND_BUFFER_SIZE, Integer.toString(sockProps_.sendBufferSize_))); + if (sockProps_.soLingerSet_) ref.add(new StringRefAddr(SOCKET_LINGER, Integer.toString(sockProps_.soLinger_))); + if (sockProps_.soTimeoutSet_) ref.add(new StringRefAddr(SOCKET_TIMEOUT, Integer.toString(sockProps_.soTimeout_))); + if (sockProps_.loginTimeoutSet_) ref.add(new StringRefAddr(SOCKET_LOGIN_TIMEOUT, Integer.toString(sockProps_.loginTimeout_))); //@st3 + if (sockProps_.tcpNoDelaySet_) ref.add(new StringRefAddr(SOCKET_TCP_NO_DELAY, (sockProps_.tcpNoDelay_ ? "true" : "false"))); + + // Add the data source properties. (unique constant identifiers for storing in JNDI). + if (getDatabaseName() != null) + ref.add(new StringRefAddr(DATABASE_NAME, getDatabaseName())); + if (getDataSourceName() != null) + ref.add(new StringRefAddr(DATASOURCE_NAME, getDataSourceName())); + if (getDescription() != null) + ref.add(new StringRefAddr(DESCRIPTION, getDescription())); + ref.add(new StringRefAddr(SERVER_NAME, getServerName())); + ref.add(new StringRefAddr(USER, getUser())); + ref.add(new StringRefAddr(KEY_RING_NAME, serialKeyRingName_)); // @F0A + if (savePasswordWhenSerialized_) { // @F0A + ref.add(new StringRefAddr(PASSWORD, new String(serialPWBytes_))); // @F0A + if (serialKeyRingPWBytes_ != null) // @F0A + ref.add(new StringRefAddr(KEY_RING_PASSWORD, new String(serialKeyRingPWBytes_))); // @F0A + else // @F0A + ref.add(new StringRefAddr(KEY_RING_PASSWORD, null)); // @F0A + } // @F0A + ref.add(new StringRefAddr(SECURE, (isSecure_ ? TRUE_ : FALSE_))); // @F0A + ref.add(new StringRefAddr(SAVE_PASSWORD, (savePasswordWhenSerialized_ ? TRUE_ : FALSE_))); // @F0A + + return ref; + } + + /** + * Returns the source of the text for REMARKS columns in ResultSets returned + * by DatabaseMetaData methods. + * @return The text source. + * Valid values include: "sql" (SQL object comment) and "system" (IBM i object description). + * The default value is "system". + **/ + public String getRemarks() + { + return properties_.getString(JDProperties.REMARKS); + } + + /** + * Returns the secondary URL. + * @return The secondary URL. + **/ + public String getSecondaryUrl() + { + return properties_.getString(JDProperties.SECONDARY_URL); + } + + //@dup + /** + * Returns the secondary URL. + * @return The secondary URL. + * Note: this method is the same as setSecondaryUrl() so that it corresponds to the connection property name + **/ + public String getSecondaryURL() + { + return getSecondaryUrl(); + } + + + /** + * Returns the name of the IBM i system. + * @return The system name. + **/ + public String getServerName() + { + return as400_.getSystemName(); + } + + + // @j1 new method + /** + * Returns the level of tracing started on the JDBC server job. + * If tracing is enabled, tracing is started when + * the client connects to the system and ends when the connection + * is disconnected. Tracing must be started before connecting to + * the system since the client enables system tracing only at connect time. + * Trace data is collected in spooled files on the system. Multiple + * levels of tracing can be turned on in combination by adding + * the constants and passing that sum on the set method. For example, + *
+    *  dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+    *  
+ * @return The tracing level. + *

The value is a combination of the following: + *

+ * + *

+ * Tracing the JDBC server job will use significant amounts of system resources. + * Additional processor resource is used to collect the data, and additional + * storage is used to save the data. Turn on tracing only to debug + * a problem as directed by IBM service. + * + **/ + public int getServerTraceCategories() + { + return properties_.getInt(JDProperties.TRACE_SERVER); + } + + //@dup + /** + * Returns the level of tracing started on the JDBC server job. + * If tracing is enabled, tracing is started when + * the client connects to the system and ends when the connection + * is disconnected. Tracing must be started before connecting to + * the system since the client enables system tracing only at connect time. + * Trace data is collected in spooled files on the system. Multiple + * levels of tracing can be turned on in combination by adding + * the constants and passing that sum on the set method. For example, + *

+     *  dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+     *  
+ * @return The tracing level. + *

The value is a combination of the following: + *

+ * + *

+ * Tracing the JDBC server job will use significant amounts of system resources. + * Additional processor resource is used to collect the data, and additional + * storage is used to save the data. Turn on tracing only to debug + * a problem as directed by IBM service. + * + * Note: this method is the same as getServerTraceCategories() so that it corresponds to the connection property name + **/ + public int getServerTrace() + { + return getServerTraceCategories(); + } + + //@STIMEOUT + /** + * Gets the socket timeout option in milliseconds. + * @return The value of the socket timeout option. + **/ + public int getSocketTimeout() + { + return getSoTimeout(); + } + + /** + * Returns how the system sorts records before sending them to the + * client. + * @return The sort value. + *

Valid values include: + *

+ * The default value is "hex". + **/ + public String getSort() + { + return properties_.getString(JDProperties.SORT); + } + + /** + * Returns the three-character language id to use for selection of a sort sequence. + * @return The three-character language id. + * The default value is ENU. + **/ + public String getSortLanguage() + { + return properties_.getString(JDProperties.SORT_LANGUAGE); + } + + /** + * Returns the library and file name of a sort sequence table stored on the + * system. + * @return The qualified sort table name. + **/ + public String getSortTable() + { + return properties_.getString(JDProperties.SORT_TABLE); + } + + /** + * Returns how the system treats case while sorting records. + * @return The sort weight. + * Valid values include: "shared" (upper- and lower-case characters are sorted as the + * same character) and "unique" (upper- and lower-case characters are sorted as + * different characters). The default value is "shared". + **/ + public String getSortWeight() + { + return properties_.getString(JDProperties.SORT_WEIGHT); + } + + /** + * Returns the time format used in time literals with SQL statements. + * @return The time format. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public String getTimeFormat() + { + return properties_.getString(JDProperties.TIME_FORMAT); + } + + /** + * Returns the time separator used in time literals within SQL + * statements. + * @return The time separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public String getTimeSeparator() + { + return properties_.getString(JDProperties.TIME_SEPARATOR); + } + + + /** + * Returns the system's transaction isolation. + * @return The transaction isolation level. + *

Valid values include: + *

+ **/ + public String getTransactionIsolation() + { + return properties_.getString(JDProperties.TRANSACTION_ISOLATION); + } + + + // @J3 No change needeadd code here. UID already properly serialized + /** + * Returns the database user property. + * @return The user. + **/ + public String getUser() + { + return as400_.getUserId(); + } + + + /** + * Returns the QAQQINI library name. + * @return The QAQQINI library name. + **/ + public String getQaqqiniLibrary() + { + return properties_.getString(JDProperties.QAQQINILIB); + } + + //@dup + /** + * Returns the QAQQINI library name. + * @return The QAQQINI library name. + * Note: this method is the same as getQaqqiniLibrary() so that it corresponds to the connection property name + **/ + public String getQaqqinilib() + { + return getQaqqiniLibrary(); + } + + + //@540 + /** + * Returns the goal the IBM i system should use with optimization of queries. + * @return the goal the IBM i system should use with optimization of queries. + *

Valid values include: + *

+ * The default value is 0. + **/ + public int getQueryOptimizeGoal() + { + return properties_.getInt(JDProperties.QUERY_OPTIMIZE_GOAL); + } + + //@550 + /** + * Returns the storage limit in megabytes, that should be used for statements executing a query in a connection. + * Note, this setting is ignored when running to i5/OS V5R4 or earlier + * You must have *JOBCTL special authority to use query storage limit with Version 6 Release 1 of IBM i. + *

Valid values are -1 to MAX_STORAGE_LIMIT megabytes. + * The default value is -1 meaning there is no limit. + **/ + public int getQueryStorageLimit() + { + return properties_.getInt(JDProperties.QUERY_STORAGE_LIMIT); + } + + /*@D4A*/ + /** + * Returns the mechanism used to implement query timeout. + * @return the mechanism used to implement query timeout. + *

Valid values include: + *

+ * The default value is 0. + **/ + public String getQueryTimeoutMechanism() + { + return properties_.getString(JDProperties.QUERY_TIMEOUT_MECHANISM); + } + + //@540 + /** + * Indicates whether lock sharing is allowed for loosely coupled transaction branches. + * @return the lock sharing setting. + *

Valid values include: + *

+ * The default value is 0. + **/ + public int getXALooselyCoupledSupport() + { + return properties_.getInt(JDProperties.XA_LOOSELY_COUPLED_SUPPORT); + } + + /** + * Initializes the transient data for object de-serialization. + **/ + private void initializeTransient() + { + Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.initializeTransient"); + + changes_ = new PropertyChangeSupport(this); + + if (isSecure_) //@B4A + as400_ = new SecureAS400(); //@B4A + else //@B4A + as400_ = new AS400(); + + // Reinitialize the serverName, user, password, keyRingName, etc. + if (serialServerName_ != null) + setServerName(serialServerName_); + + if (serialUserName_ != null) + { // @J3a + setUser(serialUserName_); + + if ((serialPWBytes_ != null) && // @J3a + (serialPWBytes_.length > 0)) // @J3a + { // @J3a + as400_.setPassword(xpwDeconfuse(serialPWBytes_)); // @J3a + } // @J3a + } + + try + { + if (serialKeyRingName_ != null && isSecure_) //@B4A + { //@J3a + if ((serialKeyRingPWBytes_ != null) && //@J3a + (serialKeyRingPWBytes_.length > 0)) //@J3a + { //@J3a + String keyRingPassword = xpwDeconfuse(serialKeyRingPWBytes_); // @J3a + ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_, keyRingPassword); //@J3A + } //@J3a + else + { //@J3a //@J3a + ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_); //@B4A + } //@J3a + } //@J3a + } + catch (PropertyVetoException pve) + { /* Will never happen */ + } + + // @J4 Make sure the prompt flag is correctly de-serialized. The problem was + // the flag would get serialized with the rest of the properties + // (in the properties_ object), but the flag would never be applied + // to the AS400 object when de-serialzed. De-serialization puts the + // flag back in properties_ but that does no good unless the value + // is passed on to the AS400 object. That is what the new code does. + // There is no affect on normal "new" objects since at the time this + // method is called properties_ is null. + try + { //@J4A //@J4A + if (properties_ != null) //@J4A + if (!isPrompt()) //@J4A + as400_.setGuiAvailable(false); //@J4A + } //@J4A + catch (PropertyVetoException pve) //@J4A + { /* Will never happen */ //@J4A + } //@J4A + + } + + //@KBA + /** + * Indicates whether true auto commit support is used. + * @return true if true auto commit support is used; false otherwise. + * The default value is false. + **/ + public boolean isTrueAutoCommit() + { + return properties_.getBoolean(JDProperties.TRUE_AUTO_COMMIT); //@true + } + + //@dup + /** + * Indicates whether true auto commit support is used. + * @return true if true auto commit support is used; false otherwise. + * The default value is false. + * Note: this method is the same as isTrueAutoCommit() so that it corresponds to the connection property name + **/ + public boolean isTrueAutocommit() + { + return isTrueAutoCommit(); + } + + + //@K54 + /** + * Indicates whether variable-length fields are compressed. + * @return true if variable-length fields are compressed; false otherwise. + * The default value is true. + **/ + public boolean isVariableFieldCompression() + { + /*@K3A*/ + String value = properties_.getString(JDProperties.VARIABLE_FIELD_COMPRESSION); + if ("true".equals(value) || + "all".equals(value) || + "insert".equals(value)) { + return true; + } else { + return false; + } + } + + + public String getVariableFieldCompression() + { + /*@K3A*/ + return properties_.getString(JDProperties.VARIABLE_FIELD_COMPRESSION); + } + + //@AC1 + /** + * Returns whether auto-commit mode is the default connection mode for new connections. + * @return Auto commit. + * The default value is true. + **/ + public boolean isAutoCommit() + { + return properties_.getBoolean(JDProperties.AUTO_COMMIT); + } + + //@CE1 + /** + * Returns whether commit or rollback throws SQLException when autocommit is enabled. + * @return Autocommit Exception. + * The default value is false. + **/ + public boolean isAutocommitException() + { + return properties_.getBoolean(JDProperties.AUTOCOMMIT_EXCEPTION); + } + + //@K24 + /** + * Indicates whether bidi implicit reordering is used. + * @return true if bidi implicit reordering is used; false otherwise. + * The default value is true. + **/ + public boolean isBidiImplicitReordering() + { + return properties_.getBoolean(JDProperties.BIDI_IMPLICIT_REORDERING); + } + + //@K24 + /** + * Indicates whether bidi numeric ordering round trip is used. + * @return true if bidi numeric ordering round trip is used; false otherwise. + * The default value is false. + **/ + public boolean isBidiNumericOrdering() + { + return properties_.getBoolean(JDProperties.BIDI_NUMERIC_ORDERING); + } + + /** + * Indicates whether a big decimal value is returned. + * @return true if a big decimal is returned; false otherwise. + * The default value is true. + **/ + public boolean isBigDecimal() + { + return properties_.getBoolean(JDProperties.BIG_DECIMAL); + } + + /** + * Indicates whether the cursor is held. + * @return true if the cursor is held; false otherwise. + * The default value is true. + **/ + public boolean isCursorHold() + { + return properties_.getBoolean(JDProperties.CURSOR_HOLD); + } + + /** + * Indicates whether data compression is used. + * @return true if data compression is used; false otherwise. + * The default value is true. + **/ + public boolean isDataCompression() + { + return properties_.getBoolean(JDProperties.DATA_COMPRESSION); + } + + /** + * Indicates whether data truncation is used. + * @return true if data truncation is used; false otherwise. + * The default value is true. + **/ + public boolean isDataTruncation() + { + return properties_.getBoolean(JDProperties.DATA_TRUNCATION); + } + + /** + * Indicates whether extended dynamic support is used. Extended dynamic + * support provides a mechanism for caching dynamic SQL statements on + * the system. The first time a particular SQL statement is prepared, it is + * stored in an SQL package on the system. + * If the package does not exist, it will be automatically created. + * On subsequent prepares of the + * same SQL statement, the system can skip a significant part of the + * processing by using information stored in the SQL package. + * @return true if extended dynamic support is used; false otherwise. + * The default value is not to use extended dynamic support. + **/ + public boolean isExtendedDynamic() + { + return properties_.getBoolean(JDProperties.EXTENDED_DYNAMIC); + } + + + // @C3A + /** + * Indicates whether the driver should request extended metadata from the + * IBM i system. If this property is set to true, the accuracy of the information + * that is returned from ResultSetMetaData methods getColumnLabel(int), + * isReadOnly(int), isSearchable(int), and isWriteable(int) will be increased. + * In addition, the ResultSetMetaData method getSchemaName(int) will be supported with this + * property set to true. However, performance will be slower with this + * property on. Leave this property set to its default (false) unless you + * need more specific information from those methods. + * + * For example, without this property turned on, isSearchable(int) will + * always return true even though the correct answer may be false because + * the driver does not have enough information from the system to make a judgment. Setting + * this property to true forces the driver to get the correct data from the IBM i system. + * + * @return true if extended metadata will be requested; false otherwise. + * The default value is false. + **/ + + public boolean isExtendedMetaData() + { + return properties_.getBoolean(JDProperties.EXTENDED_METADATA); + } + + //@dup + /** + * Indicates whether the driver should request extended metadata from the + * IBM i system. If this property is set to true, the accuracy of the information + * that is returned from ResultSetMetaData methods getColumnLabel(int), + * isReadOnly(int), isSearchable(int), and isWriteable(int) will be increased. + * In addition, the ResultSetMetaData method getSchemaName(int) will be supported with this + * property set to true. However, performance will be slower with this + * property on. Leave this property set to its default (false) unless you + * need more specific information from those methods. + * + * For example, without this property turned on, isSearchable(int) will + * always return true even though the correct answer may be false because + * the driver does not have enough information from the system to make a judgment. Setting + * this property to true forces the driver to get the correct data from the IBM i system. + * + * @return true if extended metadata will be requested; false otherwise. + * The default value is false. + * Note: this method is the same as isExtendedMetaData() so that it corresponds to the connection property name + **/ + + public boolean isExtendedMetadata() + { + return isExtendedMetaData(); + } + + + // @W1a + /** + * Indicates whether the IBM i system fully opens a file when performing a query. + * By default the system optimizes opens so they perform better. In + * certain cases an optimized open will fail. In some + * cases a query will fail when a database performance monitor + * is turned on even though the same query works with the monitor + * turned off. In this case set the full open property to true. + * This disables optimization on the system. + * @return true if files are fully opened; false otherwise. + * The default value is false. + **/ + public boolean isFullOpen() + { + return properties_.getBoolean(JDProperties.FULL_OPEN); + } + + //@dmy + /** + * Indicates whether the temporary fix for JVM 1.6 is enabled. + * @return true if enabled; false otherwise. + * The default value is true. + **/ + public boolean isJvm16Synchronize() + { + return properties_.getBoolean(JDProperties.JVM16_SYNCHRONIZE); + } + + // @A1A + /** + * Indicates whether to delay closing cursors until subsequent requests. + * @return true to delay closing cursors until subsequent requests; false otherwise. + * The default value is false. + **/ + public boolean isLazyClose() + { + return properties_.getBoolean(JDProperties.LAZY_CLOSE); + } + + //@KBL + /** + * Indicates whether input locators are of type hold. + * @return true if input locators are of type hold; false otherwise. + * The default value is true. + **/ + public boolean isHoldInputLocators() + { + return properties_.getBoolean(JDProperties.HOLD_LOCATORS); + } + + /** + * Indicates whether to add newly prepared statements to the + * SQL package specified on the "package" property. This property + * has no effect unless the extended dynamic property is set to true; + * @return true If newly prepared statements should be added to the SQL package specified + * on the "package" property; false otherwise. + * The default value is true. + **/ + public boolean isPackageAdd() + { + return properties_.getBoolean(JDProperties.PACKAGE_ADD); + } + + /** + * Indicates whether a subset of the SQL package information is cached in client memory. + * Caching SQL packages locally + * reduces the amount of communication to the IBM i system for prepares and describes. This + * property has no effect unless the extended dynamic property is set to true. + * @return true if caching is used; false otherwise. + * The defalut value is false. + **/ + public boolean isPackageCache() + { + return properties_.getBoolean(JDProperties.PACKAGE_CACHE); + } + + //@C6D Deprecated method. + /** + * Indicates whether SQL packages are cleared when they become full. This method + * has been deprecated. Package clearing and the decision for the + * threshold where package clearing is needed is now handled + * automatically by the database. + * @return Always false. This method is deprecated. + * @deprecated + **/ + public boolean isPackageClear() + { + //@C6D return properties_.getBoolean(JDProperties.PACKAGE_CLEAR); + return false; //@C6A + } + + /** + * Indicates whether data is prefetched upon executing a SELECT statement. + * This will increase performance when accessing the initial rows in the result set. + * @return If prefetch is used; false otherwise. + * The default value is prefetch data. + **/ + public boolean isPrefetch() + { + return properties_.getBoolean(JDProperties.PREFETCH); + } + + /** + * Indicates whether the user is prompted if a user name or password is + * needed to connect to the IBM i system. If a connection can not be made + * without prompting the user, and this property is set to false, then an + * attempt to connect will fail throwing an exception. + * @return true if the user is prompted for signon information; false otherwise. + * The default value is false. + **/ + public boolean isPrompt() + { + return properties_.getBoolean(JDProperties.PROMPT); + } + + //@K94 + /** + * Indicates whether the cursor is held after a rollback. + * @return true if the cursor is held; false otherwise. + * The default value is false. + **/ + public boolean isRollbackCursorHold() + { + return properties_.getBoolean(JDProperties.ROLLBACK_CURSOR_HOLD); + } + + //@KBL + /** + * Indicates whether statements remain open until a transaction boundary when autocommit is off and they + * are associated with Lob locators. + * @return true if statements are only closed at transaction boundaries; false otherwise. + * The default value is false. + **/ + public boolean isHoldStatements() + { + return properties_.getBoolean(JDProperties.HOLD_STATEMENTS); + } + + // @J3 new method + /** + * Indicates whether the password is saved locally with the rest of + * the properties when this data source object is serialized. + *

+ * If the password is saved, it is up to the application to protect + * the serialized form of the object because it contains all necessary + * information to connect to the IBM i system. The default is false. It + * is a security risk to save the password with the rest of the + * properties so by default the password is not saved. If the programmer + * chooses to accept this risk, call setSavePasswordWhenSerialized(true) + * to force the Toolbox to save the password with the other properties + * when the data source object is serialized. + * @return true if the password is saved with the rest of the properties when the + * data source object is serialized; false otherwise. + * The default value is false. + **/ + public boolean isSavePasswordWhenSerialized() + { + return savePasswordWhenSerialized_; + } + + + + + + /** + * Indicates whether a Secure Socket Layer (SSL) connection is used to communicate + * with the IBM i system. SSL connections are only available when connecting to systems + * at V4R4 or later. + * @return true if Secure Socket Layer connection is used; false otherwise. + * The default value is false. + **/ + public boolean isSecure() + { + return properties_.getBoolean(JDProperties.SECURE); + } + + //@pw3 + /** + * Returns the secure current user setting. True indicates to disallow "" and *current for user name and password. + * @return The secure current user setting. + **/ + public boolean isSecureCurrentUser() + { + return properties_.getBoolean(JDProperties.SECURE_CURRENT_USER); + } + + /** + * Indicates whether a thread is used. + * @return true if a thread is used; false otherwise. + * The default value is true. + **/ + public boolean isThreadUsed() + { + return properties_.getBoolean(JDProperties.THREAD_USED); + } + + /** + * Indicates whether trace messages should be logged. + * @return true if trace message are logged; false otherwise. + * The default value is false. + **/ + public boolean isTrace() + { + return properties_.getBoolean(JDProperties.TRACE); + } + + /** + * Indicates whether binary data is translated. If this property is set + * to true, then BINARY and VARBINARY fields are treated as CHAR and + * VARCHAR fields. + * @return true if binary data is translated; false otherwise. + * The default value is false. + **/ + public boolean isTranslateBinary() + { + return properties_.getBoolean(JDProperties.TRANSLATE_BINARY); + } + + //@PDA + /** + * Indicates how Boolean objects are interpreted when setting the value + * for a character field/parameter using the PreparedStatement.setObject(), + * CallableStatement.setObject() or ResultSet.updateObject() methods. Setting the + * property to "true", would store the Boolean object in the character field as either + * "true" or "false". Setting the property to "false", would store the Boolean object + * in the character field as either "1" or "0". + * @return true if boolean data is translated; false otherwise. + * The default value is true. + **/ + public boolean isTranslateBoolean() + { + return properties_.getBoolean(JDProperties.TRANSLATE_BOOLEAN); + } + + + /** + * Indicates whether blocking is used for update and delete operations + * @return true if enabled; false otherwise. + * The default value is false. + **/ + public boolean isUseBlockUpdate() + { + return properties_.getBoolean(JDProperties.DO_UPDATE_DELETE_BLOCKING); + } + + + /** + * Logs a message to the event log. + * @param message The message to log. + **/ + void log(String message) + { + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, message); + + if (log_ != null) + log_.log(message); + } + + /** + * Logs an exception and message to the event log. + * @param property The property to log. + * @param value The property value to log. + **/ + private void logProperty(String property, String value) + { + if (Trace.isTraceOn()) + JDTrace.logProperty (this, property, value); + + //@A8D if (log_ != null) + //@A8D log_.log(property + ": " + value); + } + + /** + * Deserializes and initializes transient data. + * @exception ClassNotFoundException If the class cannot be found. + * @exception IOException If an I/O exception occurs. + **/ + private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException + { + in.defaultReadObject(); + initializeTransient(); + } + + /** + * Removes the PropertyChangeListener. + * If the PropertyChangeListener is not in the list, nothing is done. + * @param listener The PropertyChangeListener. + * @see #addPropertyChangeListener + **/ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + if (listener == null) + throw new NullPointerException("listener"); + changes_.removePropertyChangeListener(listener); + + as400_.removePropertyChangeListener(listener); //@K1C changed to removePropertyChangeListener instead of addPropertyChangeListener + } + + /** + * Sets the level of database access for the connection. + * @param access The access level. + *

Valid values include: + *

+ * The default value is "all". + **/ + public void setAccess(String access) + { + String property = "access"; + + if (access == null) + throw new NullPointerException(property); + validateProperty(property, access, JDProperties.ACCESS); + + String old = getAccess(); + properties_.setString(JDProperties.ACCESS, access); + + changes_.firePropertyChange(property, old, access); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + access); //@A8C + } + + //@AC1 + /** + * Sets whether auto-commit mode is the default connection mode for new connections. + * @param value + * The default value is true. + **/ + public void setAutoCommit(boolean value) + { + String property = "autoCommit"; + Boolean oldValue = new Boolean(isAutoCommit()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.AUTO_COMMIT, TRUE_); + else + properties_.setString(JDProperties.AUTO_COMMIT, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@CE1 + /** + * Sets whether commit or rollback throws SQLException when autocommit is enabled. + * @param value + * The default value is false. + **/ + public void setAutocommitException(boolean value) + { + String property = "autocommitException"; + Boolean oldValue = new Boolean(isAutocommitException()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.AUTOCOMMIT_EXCEPTION, TRUE_); + else + properties_.setString(JDProperties.AUTOCOMMIT_EXCEPTION, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@KBA + /** + * Sets whether true auto commit support is used. + * @param value true if true auto commit support should be used; false otherwise. + * The default value is false. + **/ + public void setTrueAutoCommit(boolean value) + { + String property = "trueAutoCommit"; + Boolean oldValue = new Boolean(isTrueAutoCommit()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.TRUE_AUTO_COMMIT, TRUE_); //@true + else + properties_.setString(JDProperties.TRUE_AUTO_COMMIT, FALSE_); //@true + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@dup + /** + * Sets whether true auto commit support is used. + * @param value true if true auto commit support should be used; false otherwise. + * The default value is false. + * Note: this method is the same as setTrueAutoCommit() so that it corresponds to the connection property nameproperty name + **/ + public void setTrueAutocommit(boolean value) + { + setTrueAutoCommit(value); + } + + + // @C9 new method + /** + * Sets the Toolbox JDBC Driver behaviors to override. Multiple + * behaviors can be changed in combination by adding + * the constants and passing that sum on the this method. + * @param behaviors The driver behaviors to override. + *

Valid values include: + *

+ * + * Carefully consider the result of overriding the default behavior of the + * driver. For example, setting the value of this property to 1 means + * the driver will no longer throw an exception even though the JDBC 3.0 + * specification states throwing an exception is the correct behavior. + * Be sure your application correctly handles the altered behavior. + * + **/ + public void setBehaviorOverride(int behaviors) + { + String property = "behaviorOverride"; + + Integer oldValue = new Integer(getBehaviorOverride()); + Integer newValue = new Integer(behaviors); + + properties_.setString(JDProperties.BEHAVIOR_OVERRIDE, newValue.toString()); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + behaviors); + } + + + + + //@B2A + /** + * Sets the output string type of bidi data. See + * BidiStringType for more information and valid values. + **/ + public void setBidiStringType(int bidiStringType) //@B3C + { + String property = "bidiStringType"; //@B3C + + //@B3D if (bidiStringType == null) + //@B3D throw new NullPointerException(property); + Integer oldBidiStringType = new Integer(getBidiStringType()); //@B3A + Integer newBidiStringType = new Integer(bidiStringType); //@B3A + + validateProperty(property, newBidiStringType.toString(), JDProperties.BIDI_STRING_TYPE); //@B3C + + properties_.setString(JDProperties.BIDI_STRING_TYPE, newBidiStringType.toString()); //@B3C + + changes_.firePropertyChange(property, oldBidiStringType, newBidiStringType); //@B3C + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + bidiStringType); + } + + //@K24 + /** + * Sets whether bidi implicit reordering is used. + * In this version, the parameter is used to determine whether Bidi layout + * transformation should be applied to meta-data such as columns names. + * @param value true if implicit reordering should be used; false otherwise. + * The default value is true. + **/ + public void setBidiImplicitReordering(boolean value) + { + String property = "bidiImplicitReordering"; + Boolean oldValue = new Boolean(isBidiImplicitReordering()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.BIDI_IMPLICIT_REORDERING, TRUE_); + else + properties_.setString(JDProperties.BIDI_IMPLICIT_REORDERING, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@K24 + /** + * Sets whether bidi numeric ordering round trip is used. + * @param value true if numeric ordering round trip should be used; false otherwise. + * The default value is false. + **/ + public void setBidiNumericOrdering(boolean value) + { + String property = "bidiNumericOrdering"; + Boolean oldValue = new Boolean(isBidiNumericOrdering()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.BIDI_NUMERIC_ORDERING, TRUE_); + else + properties_.setString(JDProperties.BIDI_NUMERIC_ORDERING, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + /** + * Sets whether a big decimal value is returned. + * @param value true if a big decimal is returned; false otherwise. + * The default value is true. + **/ + public void setBigDecimal(boolean value) + { + String property = "bigDecimal"; + Boolean oldValue = new Boolean(isBigDecimal()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.BIG_DECIMAL, TRUE_); + else + properties_.setString(JDProperties.BIG_DECIMAL, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + value); //@A8C + } + + /** + * Sets the criteria for retrieving data from the IBM i system in + * blocks of records. Specifying a non-zero value for this property + * will reduce the frequency of communication to the system, and + * therefore increase performance. + * @param blockCriteria The block criteria. + *

Valid values include: + *

+ **/ + public void setBlockCriteria(int blockCriteria) + { + String property = "blockCriteria"; + Integer oldCriteria = new Integer(getBlockCriteria()); + Integer newCriteria = new Integer(blockCriteria); + + validateProperty(property, newCriteria.toString(), JDProperties.BLOCK_CRITERIA); + + properties_.setString(JDProperties.BLOCK_CRITERIA, newCriteria.toString()); + changes_.firePropertyChange(property, oldCriteria, newCriteria); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + blockCriteria); //@A8C + } + + /** + * Sets the block size in kilobytes to retrieve from the IBM i system and + * cache on the client. This property has no effect unless the block criteria + * property is non-zero. Larger block sizes reduce the frequency of + * communication to the system, and therefore may increase performance. + * @param blockSize The block size in kilobytes. + *

Valid values include: + *

+ **/ + public void setBlockSize(int blockSize) + { + String property = "blockSize"; + + Integer oldBlockSize = new Integer(getBlockSize()); + Integer newBlockSize = new Integer(blockSize); + + validateProperty(property, newBlockSize.toString(), JDProperties.BLOCK_SIZE); + + properties_.setString(JDProperties.BLOCK_SIZE, new Integer(blockSize).toString()); + changes_.firePropertyChange(property, oldBlockSize, newBlockSize); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + blockSize); //@A8C + } + + //@cc1 + /** + * This method sets concurrent access resolution. This method overrides the setting of ConcurrentAccessResolution on the datasource or connection + * URL properties. This method has no effect on + * IBM i V6R1 or earlier. + * The possible values for this property are {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} and + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS}, + * with the property defaulting to {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}. + * Setting this property to default exhibits the default behavior on the servers + * i.e., the semantic applied for read + * transactions to avoid locks will be determined by the server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED} specifies that driver will flow USE CURRENTLY COMMITTED + * to server. Whether CURRENTLY COMMITTED will actually be in effect is + * ultimately determined by server. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME} specifies that driver will flow WAIT FOR OUTCOME + * to server. This will disable the CURRENTLY COMMITTED behavior at the server, + * if enabled, and the server will wait for the commit or rollback of data in the process of + * being updated. + * + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} specifies that driver will flow SKIP LOCKS + * to server. This directs the database manager to skip records in the case of record lock conflicts. + * + * @param concurrentAccessResolution The current access resolution setting. Possible valuse: + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_NOT_SET}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_USE_CURRENTLY_COMMITTED}, + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_WAIT_FOR_OUTCOME}, or + * {@link com.ibm.as400.access.AS400JDBCDataSource#CONCURRENTACCESS_SKIP_LOCKS} + */ + public void setConcurrentAccessResolution (int concurrentAccessResolution) + { + String property = "concurrentAccessResolution"; + + Integer oldValue = new Integer(getConcurrentAccessResolution()); + Integer newValue = new Integer(concurrentAccessResolution); + + validateProperty(property, newValue.toString(), JDProperties.CONCURRENT_ACCESS_RESOLUTION); + + properties_.setString(JDProperties.CONCURRENT_ACCESS_RESOLUTION, newValue.toString()); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + concurrentAccessResolution ); + } + + //@C8A + /** + * Sets the cursor sensitivity to be requested from the database. If the resultSetType is + * ResultSet.TYPE_FORWARD_ONLY or ResultSet.TYPE_SCROLL_SENSITIVE, the value of this property + * will control what cursor sensitivity is requested from the database. If the resultSetType + * is ResultSet.TYPE_SCROLL_INSENSITIVE, this property will be ignored. + * + *

Valid values include: + *

+ * The default is "asensitive". + * + * This property is ignored when connecting to systems + * running OS/400 V5R1 and earlier. + **/ + public void setCursorSensitivity(String cursorSensitivity) + { + String property = "cursorSensitivity"; + + String oldCursorSensitivity = getCursorSensitivity(); + String newCursorSensitivity = cursorSensitivity; + + validateProperty(property, newCursorSensitivity, JDProperties.CURSOR_SENSITIVITY); + + properties_.setString(JDProperties.CURSOR_SENSITIVITY, cursorSensitivity); + changes_.firePropertyChange(property, oldCursorSensitivity, newCursorSensitivity); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + cursorSensitivity); + } + + + /** + * Sets whether the cursor is held. + * @param cursorHold true if the cursor is held; false otherwise. The default value is true. + **/ + public void setCursorHold(boolean cursorHold) + { + String property = "cursorHold"; + Boolean oldHold = new Boolean(isCursorHold()); + Boolean newHold = new Boolean(cursorHold); + + if (cursorHold) + properties_.setString(JDProperties.CURSOR_HOLD, TRUE_); + else + properties_.setString(JDProperties.CURSOR_HOLD, FALSE_); + + changes_.firePropertyChange(property, oldHold, newHold); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + cursorHold); //@A8C + } + + /** + * Sets the database name. + * This property is ignored when connecting to systems + * running OS/400 V5R1 and earlier. + * If a database name is specified it must exist in the relational + * database directory on the system. Use CL command WRKRDBDIRE + * to view the directory. + * The following criteria are used to determine + * which database is accessed: + *
    + *
  1. If a database name is specified, that database is used. Attempts + * to connect will fail if the database does not exist. + *
  2. If special value *SYSBAS is specified, the system default database is used. + *
  3. If a database name is not specified, the database specified + * in the job description for the user profile is used. + *
  4. If a database name is not specified and a database is not specified + * in the job description for the user profile, the system default + * database is used. + *
+ * @param databaseName The database name or *SYSBAS. + **/ + public void setDatabaseName(String databaseName) + { + String property = DATABASE_NAME; + + if (databaseName == null) + throw new NullPointerException(property); + + String old = getDatabaseName(); + + // @J2d databaseName_ = databaseName; + // @J2d changes_.firePropertyChange(property, old, databaseName); + // @J2d logProperty("database", databaseName_); + + properties_.setString(JDProperties.DATABASE_NAME, databaseName); // @J2a + changes_.firePropertyChange(property, old, databaseName); // @J2a + // @J2a + if (JDTrace.isTraceOn()) // @J2a + JDTrace.logInformation (this, property + ": " + databaseName); // @J2a + } + + /** + * Sets whether to use data compression. The default value is true. + * @param compression true if data compression is used; false otherwise. + **/ + public void setDataCompression(boolean compression) + { + Boolean oldCompression = new Boolean(isDataCompression()); + Boolean newCompression = new Boolean(compression); + + if (compression) + properties_.setString(JDProperties.DATA_COMPRESSION, TRUE_); + else + properties_.setString(JDProperties.DATA_COMPRESSION, FALSE_); + + changes_.firePropertyChange("dataCompression", oldCompression, newCompression); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "dataCompression: " + compression); //@A8C + } + + /** + * Sets the data source name. + * This property can be used for connection pooling implementations. + * @param dataSourceName The data source name. + **/ + public void setDataSourceName(String dataSourceName) + { + String property = DATASOURCE_NAME; + + if (dataSourceName == null) + throw new NullPointerException(property); + + String old = getDataSourceName(); + + dataSourceName_ = dataSourceName; + + changes_.firePropertyChange(property, old, dataSourceName); + + logProperty("dataSource", dataSourceName_); + } + + /** + * Sets whether to use data truncation. The default value is true. + * @param truncation true if data truncation is used; false otherwise. + **/ + public void setDataTruncation(boolean truncation) + { + Boolean oldTruncation = new Boolean(isDataTruncation()); + Boolean newTruncation = new Boolean(truncation); + + if (truncation) + properties_.setString(JDProperties.DATA_TRUNCATION, TRUE_); + else + properties_.setString(JDProperties.DATA_TRUNCATION, FALSE_); + + changes_.firePropertyChange("dataTruncation", oldTruncation, newTruncation); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "dataTruncation: " + truncation); //@A8C + } + + /** + * Sets the date format used in date literals within SQL statements. + * @param dateFormat The date format. + *

Valid values include: + *

+ * The default is based on the server job. + **/ + public void setDateFormat(String dateFormat) + { + String property = "dateFormat"; + + if (dateFormat == null) + throw new NullPointerException(property); + validateProperty(property, dateFormat, JDProperties.DATE_FORMAT); + + String old = getDateFormat(); + + properties_.setString(JDProperties.DATE_FORMAT, dateFormat); + + changes_.firePropertyChange(property, old, dateFormat); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + dateFormat); //@A8C + } + + /** + * Sets the date separator used in date literals within SQL statements. + * This property has no effect unless the "data format" property is set to: + * "julian", "mdy", "dmy", or "ymd". + * @param dateSeparator The date separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public void setDateSeparator(String dateSeparator) + { + String property = "dateSeparator"; + if (dateSeparator == null) + throw new NullPointerException(property); + validateProperty(property, dateSeparator, JDProperties.DATE_SEPARATOR); + + String old = getDateSeparator(); + + properties_.setString(JDProperties.DATE_SEPARATOR, dateSeparator); + + changes_.firePropertyChange(property, old, dateSeparator); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + dateSeparator); //@A8C + } + + //@DFA + /** + * Sets the decfloat rounding mode. + * @param decfloatRoundingMode The decfloat rounding mode. + *

Valid values include: + *

+ **/ + public void setDecfloatRoundingMode(String decfloatRoundingMode) + { + String property = "decfloatRoundingMode"; + if (decfloatRoundingMode == null) + throw new NullPointerException(property); + validateProperty(property, decfloatRoundingMode, JDProperties.DECFLOAT_ROUNDING_MODE); + + String old = getDecfloatRoundingMode(); + + properties_.setString(JDProperties.DECFLOAT_ROUNDING_MODE, decfloatRoundingMode); + + changes_.firePropertyChange(property, old, decfloatRoundingMode); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + decfloatRoundingMode); + } + + /** + * Sets the decimal separator used in numeric literals within SQL + * statements. + * @param decimalSeparator The decimal separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public void setDecimalSeparator(String decimalSeparator) + { + String property = "decimalSeparator"; + if (decimalSeparator == null) + throw new NullPointerException(property); + validateProperty(property, decimalSeparator, JDProperties.DECIMAL_SEPARATOR); + + String old = getDecimalSeparator(); + + properties_.setString(JDProperties.DECIMAL_SEPARATOR, decimalSeparator); + + changes_.firePropertyChange(property, old, decimalSeparator); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + decimalSeparator); //@A8C + } + + //@igwrn + /** + * Sets the ignore warnings property. + * @param ignoreWarnings Specifies a list of SQL states for which the driver should not create warning objects. + **/ + public void setIgnoreWarnings(String ignoreWarnings) + { + String property = "ignoreWarnings"; + if (ignoreWarnings == null) + throw new NullPointerException(property); + + String old = getIgnoreWarnings(); + + properties_.setString(JDProperties.IGNORE_WARNINGS, ignoreWarnings); + + changes_.firePropertyChange(property, old, ignoreWarnings); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + ignoreWarnings); + } + + /** + * Sets the data source description. + * @param description The description. + **/ + public void setDescription(String description) + { + String property = DESCRIPTION; + if (description == null) + throw new NullPointerException(property); + + String old = getDescription(); + + description_ = description; + + changes_.firePropertyChange(property, old, description); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + description); //@A8C + } + + /** + * Sets how the IBM i system sorts records before sending them to the client. + * @param sort The sort value. + *

Valid values include: + *

+ * The default value is "hex". + **/ + public void setSort(String sort) + { + String property = "sort"; + if (sort == null) + throw new NullPointerException(property); + + //@JOB fix to allow "sort=job" but use default value + if(sort.equals("job")) //@JOB + { //@JOB + if (JDTrace.isTraceOn()) //@JOB + JDTrace.logInformation (this, property + ": " + getSort() + " (warning: " + getSort() + " will be used since sort=job is not valid)"); //@JOB + return; //return and allow default setting to be used //@JOB + } //@JOB + + + validateProperty(property, sort, JDProperties.SORT); + String old = getSort(); + + properties_.setString(JDProperties.SORT, sort); + + changes_.firePropertyChange(property, old, sort); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + sort); //@A8C + } + + /** + * Sets the amount of detail to be returned in the message for errors + * occurring on the IBM i system. + * @param errors The error message level. + * Valid values include: "basic" and "full". The default value is "basic". + **/ + public void setErrors(String errors) + { + String property = "errors"; + if (errors == null) + throw new NullPointerException(property); + validateProperty(property, errors, JDProperties.ERRORS); + + String old = getErrors(); + properties_.setString(JDProperties.ERRORS, errors); + + changes_.firePropertyChange(property, old, errors); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + errors); //@A8C + } + + /** + * Sets whether to use extended dynamic support. Extended dynamic + * support provides a mechanism for caching dynamic SQL statements on + * the IBM i system. The first time a particular SQL statement is prepared, it is + * stored in an SQL package on the system. + * If the package does not exist, it will be automatically created. + * On subsequent prepares of the + * same SQL statement, the system can skip a significant part of the + * processing by using information stored in the SQL package. If this + * is set to "true", then a package name must be set using the "package" + * property. + * @param extendedDynamic If extended dynamic support is used; false otherwise. + * The default value is not to use extended dynamic support. + **/ + public void setExtendedDynamic(boolean extendedDynamic) + { + Boolean oldValue = new Boolean(isExtendedDynamic()); + Boolean newValue = new Boolean(extendedDynamic); + + if (extendedDynamic) + properties_.setString(JDProperties.EXTENDED_DYNAMIC, TRUE_); + else + properties_.setString(JDProperties.EXTENDED_DYNAMIC, FALSE_); + + changes_.firePropertyChange("extendedDynamic", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "extendedDynamic: " + extendedDynamic); //@A8C + } + + // @C3A + /** + * Sets whether the driver should request extended metadata from the + * IBM i system. This property is ignored when connecting to systems + * running OS/400 V5R1 and earlier. + * If this property is set to true and connecting to a system running + * OS/400 V5R2 or IBM i, the accuracy of the information + * that is returned from ResultSetMetaData methods getColumnLabel(int), + * isReadOnly(int), isSearchable(int), and isWriteable(int) will be increased. + * In addition, the ResultSetMetaData method getSchemaName(int) will be supported with this + * property set to true. However, performance will be slower with this + * property on. Leave this property set to its default (false) unless you + * need more specific information from those methods. + * + * For example, without this property turned on, isSearchable(int) will + * always return true even though the correct answer may be false because + * the driver does not have enough information from the system to make a judgment. Setting + * this property to true forces the driver to get the correct data from the system. + * + * @param extendedMetaData True to request extended metadata from the system, false otherwise. + * The default value is false. + **/ + public void setExtendedMetaData(boolean extendedMetaData) + { + Boolean oldValue = new Boolean(isExtendedMetaData()); + Boolean newValue = new Boolean(extendedMetaData); + + if (extendedMetaData) + properties_.setString(JDProperties.EXTENDED_METADATA, TRUE_); + else + properties_.setString(JDProperties.EXTENDED_METADATA, FALSE_); + + changes_.firePropertyChange("extendedMetaData", oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "extendedMetaData: " + extendedMetaData); + } + + //@dup + /** + * Sets whether the driver should request extended metadata from the + * IBM i system. This property is ignored when connecting to systems + * running OS/400 V5R1 and earlier. + * If this property is set to true and connecting to a system running + * OS/400 V5R2 or IBM i, the accuracy of the information + * that is returned from ResultSetMetaData methods getColumnLabel(int), + * isReadOnly(int), isSearchable(int), and isWriteable(int) will be increased. + * In addition, the ResultSetMetaData method getSchemaName(int) will be supported with this + * property set to true. However, performance will be slower with this + * property on. Leave this property set to its default (false) unless you + * need more specific information from those methods. + * + * For example, without this property turned on, isSearchable(int) will + * always return true even though the correct answer may be false because + * the driver does not have enough information from the system to make a judgment. Setting + * this property to true forces the driver to get the correct data from the system. + * + * @param extendedMetaData True to request extended metadata from the system, false otherwise. + * The default value is false. + * Note: this method is the same as setExtendedMetaData() so that it corresponds to the connection property name + **/ + public void setExtendedMetadata(boolean extendedMetaData) + { + setExtendedMetaData(extendedMetaData); + } + + + // @W1a new method + /** + * Sets whether to fully open a file when performing a query. + * By default the IBM i system optimizes opens so they perform better. + * In most cases optimization functions correctly and improves + * performance. Running a query repeatedly + * when a database performance monitor is turned on may fail + * because of the optimization, however. + * Leave this property set to its default (false) until + * you experience errors running queries with monitors + * turned on. At that time set the property to true which + * will disable the optimization. + * @param fullOpen True to fully open a file (turn off optimizations), false + * to allow optimizations. The default value is false. + **/ + public void setFullOpen(boolean fullOpen) + { + Boolean oldValue = new Boolean(isFullOpen()); + Boolean newValue = new Boolean(fullOpen); + + if (fullOpen) + properties_.setString(JDProperties.FULL_OPEN, TRUE_); + else + properties_.setString(JDProperties.FULL_OPEN, FALSE_); + + changes_.firePropertyChange("fullOpen", oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "fullOpen: " + fullOpen); + } + + //@KBL + /** + * Sets whether input locators are allocated as hold locators. + * @param value true if locators should be allocated as hold locators; false otherwise. + * The default value is true. + **/ + public void setHoldInputLocators(boolean value) + { + String property = "holdInputLocators"; + Boolean oldValue = new Boolean(isHoldInputLocators()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.HOLD_LOCATORS, TRUE_); + else + properties_.setString(JDProperties.HOLD_LOCATORS, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@KBL + /** + * Sets whether statements should remain open until a transaction boundary when autocommit is off + * and they are associated with Lob locators. + * @param value true if statements should remain open; false otherwise. + * The default value is false. + **/ + public void setHoldStatements(boolean value) + { + String property = "holdStatements"; + Boolean oldValue = new Boolean(isHoldStatements()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.HOLD_STATEMENTS, TRUE_); + else + properties_.setString(JDProperties.HOLD_STATEMENTS, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + //@dmy + /** + * Indicates whether the temporary fix for JVM 1.6 is enabled. + * @param value true if JVM 1.6 fix is enabled; false otherwise. + * The default value is true. + **/ + public void setJvm16Synchronize(boolean value) + { + String property = "jvm16 synchronize"; + Boolean oldValue = new Boolean(isJvm16Synchronize()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.JVM16_SYNCHRONIZE, TRUE_); + else + properties_.setString(JDProperties.JVM16_SYNCHRONIZE, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + // @A1A + /** + * Sets whether to delay closing cursors until subsequent requests. + * @param lazyClose true to delay closing cursors until subsequent requests; false otherwise. + The default value is false. + **/ + public void setLazyClose(boolean lazyClose) + { + Boolean oldValue = new Boolean(isLazyClose()); + Boolean newValue = new Boolean(lazyClose); + + if (lazyClose) + properties_.setString(JDProperties.LAZY_CLOSE, TRUE_); + else + properties_.setString(JDProperties.LAZY_CLOSE, FALSE_); + + changes_.firePropertyChange("lazyClose", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "lazyClose: " + lazyClose); //@A8C + } + + /** + * Sets the libraries to add to the server job's library list. + * The libraries are delimited by commas or spaces, and + * "*LIBL" may be used as a place holder for the server job's + * current library list. The library list is used for resolving + * unqualified stored procedure calls and finding schemas in + * DatabaseMetaData catalog methods. If "*LIBL" is not specified, + * the specified libraries will replace the server job's + * current library list. + * @param libraries The library list. + **/ + public void setLibraries(String libraries) + { + String property = "libraries"; + if (libraries == null) + throw new NullPointerException("libraries"); + + String old = getLibraries(); + properties_.setString(JDProperties.LIBRARIES, libraries); + + changes_.firePropertyChange(property, old, libraries); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + libraries); //@A8C + } + + /** + * Sets the maximum LOB (large object) size in bytes that + * can be retrieved as part of a result set. LOBs that are larger + * than this threshold will be retrieved in pieces using extra + * communication to the IBM i system. Larger LOB thresholds will reduce + * the frequency of communication to the system, but will download + * more LOB data, even if it is not used. Smaller LOB thresholds may + * increase frequency of communication to the system, but will only + * download LOB data as it is needed. + * + * @param threshold The lob threshold. Valid range is 0-16777216. + * The default value is 32768. + **/ + public void setLobThreshold(int threshold) + { + String property = "threshold"; + if (threshold < 0 || threshold > MAX_THRESHOLD) + throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID); + + Integer oldValue = new Integer(getLobThreshold()); + Integer newValue = new Integer(threshold); + + properties_.setString(JDProperties.LOB_THRESHOLD, new Integer(threshold).toString()); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + threshold); //@A8C + } + + /** + * Sets the maximum time in seconds that this data source can wait while attempting to connect to a database. + * A value of zero specifies that the timeout is the system default if one exists; otherwise it specifies that + * there is no timeout. The default value is initially zero. + * @param timeout The login timeout in seconds. + **/ + public void setLoginTimeout(int timeout) throws SQLException + { + + //@STIMEOUT setSoTimeout(timeout * 1000); //@K5A setSoTimeout takes milliseconds as a parameter //@STIMEOUT separate login and socket timeout into two separtate properties + sockProps_.setLoginTimeout(timeout * 1000); //@st3 + String property = "loginTimeout"; //@K5A + + Integer oldValue = new Integer(getLoginTimeout()); //@K5A + Integer newValue = new Integer(timeout); //@K5A + + properties_.setString(JDProperties.LOGIN_TIMEOUT, newValue.toString()); //@K5A + + changes_.firePropertyChange(property, oldValue, newValue); //@K5A + + if (JDTrace.isTraceOn()) //@K5A + JDTrace.logInformation (this, property + ": " + timeout); //@K5A + + //@K5D JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED); + } + + /** + * Sets the log writer for this data source. + * @param writer The log writer; to disable, set to null. + * @exception SQLException If a database error occurs. + **/ + public void setLogWriter(PrintWriter writer) throws SQLException + { + String property = "writer"; + + //@C4D if (writer == null) + //@C4D throw new NullPointerException(property); + + PrintWriter old = getLogWriter(); + writer_ = writer; + changes_.firePropertyChange(property, old, writer); + + if (writer == null) //@C4A + { //@C4A + log_ = null; //@C4A + return; //@C4A + } //@C4A + + log_ = new EventLog(writer); + } + + //@PDA + /** + * Sets how to retrieve DatabaseMetaData. + * If set to 0, database metadata will be retrieved through the ROI data flow. + * If set to 1, database metadata will be retrieved by calling system stored procedures. + * The methods that currently are available through stored procedures are: + * getColumnPrivileges + * @param mds The setting for metadata source + * The default value is 1. + **/ + public void setMetaDataSource(int mds) + { + String property = "metaDataSource"; + + Integer oldValue = new Integer(getMetaDataSource()); + Integer newValue = new Integer(mds); + + properties_.setString(JDProperties.METADATA_SOURCE, newValue.toString()); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + mds); + } + + + //@dup + /** + * Sets how to retrieve DatabaseMetaData. + * If set to 0, database metadata will be retrieved through the ROI data flow. + * If set to 1, database metadata will be retrieved by calling system stored procedures. + * The methods that currently are available through stored procedures are: + * getColumnPrivileges + * @param mds The setting for metadata source + * The default value is 1. + * Note: this method is the same as setMetaDataSource() so that it corresponds to the connection property name + **/ + public void setMetadataSource(int mds) + { + setMetaDataSource(mds); + } + + + /** + * Sets the naming convention used when referring to tables. + * @param naming The naming convention. Valid values include: "sql" (e.g. schema.table) + * and "system" (e.g. schema/table). The default value is "sql". + **/ + public void setNaming(String naming) + { + String property = "naming"; + if (naming == null) + throw new NullPointerException("naming"); + validateProperty(property, naming, JDProperties.NAMING); + + String old = getNaming(); + properties_.setString(JDProperties.NAMING, naming); + + changes_.firePropertyChange(property, old, naming); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + naming); //@A8C + } + + /** + * Sets the base name of the SQL package. Note that only the + * first six characters are used to generate the name of the SQL package on the IBM i system. + * This property has no effect unless + * the extended dynamic property is set to true. In addition, this property + * must be set if the extended dynamic property is set to true. + * @param packageName The base name of the SQL package. + **/ + public void setPackage(String packageName) + { + String property = "packageName"; + if (packageName == null) + throw new NullPointerException(property); + + String old = getPackage(); + properties_.setString(JDProperties.PACKAGE, packageName); + + changes_.firePropertyChange(property, old, packageName); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + packageName); //@A8C + } + + /** + * Sets whether to add newly prepared statements to the SQL package + * specified on the "package" property. This property + * has no effect unless the extended dynamic property is set to true. + * @param add If newly prepared statements should be added to the SQL package specified on + * the "package" property; false otherwise. + * The default value is true. + **/ + public void setPackageAdd(boolean add) + { + Boolean oldValue = new Boolean(isPackageAdd()); + Boolean newValue = new Boolean(add); + + if (add) + properties_.setString(JDProperties.PACKAGE_ADD, TRUE_); + else + properties_.setString(JDProperties.PACKAGE_ADD, FALSE_); + + changes_.firePropertyChange("packageAdd", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "packageAdd: " + add); //@A8C + } + + /** + * Sets whether to cache a subset of the SQL package information in client memory. + * Caching SQL packages locally + * reduces the amount of communication to the IBM i system for prepares and describes. This + * property has no effect unless the extended dynamic property is set to true. + * @param cache If caching is used; false otherwise. The default value is false. + **/ + public void setPackageCache(boolean cache) + { + Boolean oldValue = new Boolean(isPackageCache()); + Boolean newValue = new Boolean(cache); + + if (cache) + properties_.setString(JDProperties.PACKAGE_CACHE, TRUE_); + else + properties_.setString(JDProperties.PACKAGE_CACHE, FALSE_); + + changes_.firePropertyChange("packageCache", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "packageCache: " + cache); //@A8C + } + + + //@C6C Changed javadoc since package clearing is now done automatically + //@C6C by the database. + /** + * Sets whether to clear SQL packages when they become full. This method + * has been deprecated. Package clearing and the decision for the + * threshold where package clearing is needed is now handled + * automatically by the database. + * @param clear If the SQL package are cleared when full; false otherwise. + * @deprecated + **/ + public void setPackageClear(boolean clear) + { + //@C6D Package clearing and the decision for the + //@C6D threshold where package clearing is needed is now handled + //@C6D automatically by the database. + + //@C6D Boolean oldValue = new Boolean(isPackageClear()); + //@C6D Boolean newValue = new Boolean(clear); + + //@C6D String value = null; + //@C6D if (clear) + //@C6D properties_.setString(JDProperties.PACKAGE_CLEAR, TRUE_); + //@C6D else + //@C6D properties_.setString(JDProperties.PACKAGE_CLEAR, FALSE_); + + //@C6D changes_.firePropertyChange("packageClear", oldValue, newValue); + + //@C6D if (JDTrace.isTraceOn()) //@A8C + //@C6D JDTrace.logInformation (this, "packageClear: " + clear); //@A8C + } + + + /** + * Sets the type of SQL statement to be stored in the SQL package. This can + * be useful to improve the performance of complex join conditions. This + * property has no effect unless the extended dynamic property is set to true. + * @param packageCriteria The type of SQL statement. + * Valid values include: "default" (only store SQL statements with parameter + * markers in the package), and "select" (store all SQL SELECT statements + * in the package). The default value is "default". + **/ + public void setPackageCriteria(String packageCriteria) + { + String property = "packageCriteria"; + + if (packageCriteria == null) + throw new NullPointerException(property); + validateProperty(property, packageCriteria, JDProperties.PACKAGE_CRITERIA); + + String old = getPackageCriteria(); + properties_.setString(JDProperties.PACKAGE_CRITERIA, packageCriteria); + + changes_.firePropertyChange(property, old, packageCriteria); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + packageCriteria); //@A8C + } + + /** + * Sets the action to take when SQL package errors occur. When an SQL package + * error occurs, the driver will optionally throw an SQLException or post a + * warning to the Connection, based on the value of this property. This property + * has no effect unless the extended dynamic property is set to true. + * @param packageError The action when SQL errors occur. + * Valid values include: "exception", "warning", and "none". The default value is "warning". + **/ + public void setPackageError(String packageError) + { + String property = "packageError"; + if (packageError == null) + throw new NullPointerException(property); + validateProperty(property, packageError, JDProperties.PACKAGE_ERROR); + + String old = getPackageError(); + properties_.setString(JDProperties.PACKAGE_ERROR, packageError); + + changes_.firePropertyChange(property, old, packageError); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + packageError); //@A8C + } + /** + * Sets the library for the SQL package. This property has no effect unless + * the extended dynamic property is set to true. + * @param packageLibrary The SQL package library. The default package library is "QGPL". + **/ + public void setPackageLibrary(String packageLibrary) + { + String property = "packageLibrary"; + if (packageLibrary == null) + throw new NullPointerException(property); + + String old = getPackageLibrary(); + properties_.setString(JDProperties.PACKAGE_LIBRARY, packageLibrary); + + changes_.firePropertyChange(property, old, packageLibrary); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + packageLibrary); //@A8C + } + + /** + * Sets the database password. + * @param password The password. + **/ + public void setPassword(String password) + { + as400_.setPassword(password); + serialPWBytes_ = xpwConfuse(password); //@J3a + log(ResourceBundleLoader.getText("AS400_JDBC_DS_PASSWORD_SET")); //@A9C + } + + /** + * Sets whether to prefetch data upon executing a SELECT statement. + * This will increase performance when accessing the initial rows in the result set. + * @param prefetch If prefetch is used; false otherwise. + * The default value is to prefectch data. + **/ + public void setPrefetch(boolean prefetch) + { + Boolean oldValue = new Boolean(isPrefetch()); + Boolean newValue = new Boolean(prefetch); + + if (prefetch) + properties_.setString(JDProperties.PREFETCH, TRUE_); + else + properties_.setString(JDProperties.PREFETCH, FALSE_); + + changes_.firePropertyChange("prefetch", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "prefetch: " + prefetch); //@A8C + } + + /** + * Sets whether the user should be prompted if a user name or password is + * needed to connect to the IBM i system. If a connection can not be made + * without prompting the user, and this property is set to false, then an + * attempt to connect will fail. + * @param prompt true if the user is prompted for signon information; false otherwise. + * The default value is false. + **/ + public void setPrompt(boolean prompt) + { + Boolean oldValue = new Boolean(isPrompt()); + Boolean newValue = new Boolean(prompt); + + if (prompt) + properties_.setString(JDProperties.PROMPT, TRUE_); + else + properties_.setString(JDProperties.PROMPT, FALSE_); + + try + { //@C2A + as400_.setGuiAvailable(prompt); //@C2A + } //@C2A + catch (PropertyVetoException vp) //@C2A + { /* ignore */ //@C2A + } //@C2A + + changes_.firePropertyChange("prompt", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "prompt: " + prompt); //@A8C + } + + // @F0D - Removed unused method + ///** + //* Sets the JDBC properties. + //* @param Properties The JDBC properties list. + //**/ + //void setProperties(Reference reference) + //{ + // /* + // * Implementation note: This method is called from AS400JDBCObjectFactory.getObjectInstance + // */ + // if (reference == null) + // throw new NullPointerException("reference"); + // + // Properties properties = new Properties(); + // + // Enumeration list = reference.getAll(); + // while (list.hasMoreElements()) + // { + // StringRefAddr refAddr = (StringRefAddr)list.nextElement(); + // String property = refAddr.getType(); + // String value = (String)reference.get(property).getContent(); + // + // if (property.equals(DATABASE_NAME)) // constant identifiers were used to store in JNDI. + // setDatabaseName(value); + // else if (property.equals(DATASOURCE_NAME)) + // setDataSourceName(value); + // else if (property.equals(DESCRIPTION)) + // setDescription(value); + // else if (property.equals(SERVER_NAME)) + // setServerName(value); + // else if (property.equals(USER)) + // setUser(value); + // else if (property.equals(PASSWORD)) { + // // get the password back from the serialized char[] + // serialPWBytes_ = value.toCharArray(); + // // decode the password and set it on the as400 + // as400_.setPassword(xpwDeconfuse(serialPWBytes_)); + // } + // else if (property.equals(KEY_RING_NAME)) { + // // set the key ring name + // serialKeyRingName_ = value; + // } + // else if (property.equals(KEY_RING_PASSWORD)) { + // // get the key ring password back from the serialized char[] + // if (value != null) + // serialKeyRingPWBytes_ = value.toCharArray(); + // } + // else if (property.equals(SECURE)) { + // // set the isSecure_ flag + // isSecure_ = value.equals(TRUE_) ? true : false; + // } + // else if (property.equals(SAVE_PASSWORD)) { + // // set the savePasswordWhenSerialized_ flag + // savePasswordWhenSerialized_ = value.equals(TRUE_) ? true : false; + // } + // else + // { + // properties.put(property, value); + // } + // } + // properties_ = new JDProperties(properties, null); + // + // // get the prompt property and set it back in the as400 object + // String prmpt = properties_.getString(JDProperties.PROMPT); + // if (prmpt != null && prmpt.equalsIgnoreCase(FALSE_)) + // setPrompt(false); + // else if (prmpt != null && prmpt.equalsIgnoreCase(TRUE_)) + // setPrompt(true); + // + // // if the system is secure create a SecureAS400 object + // if (isSecure_) { + // try + // { + // as400_ = new SecureAS400(as400_); + // ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_, xpwDeconfuse(serialKeyRingPWBytes_)); + // } + // catch (PropertyVetoException pe) + // { /* will never happen */ + // } + // } + //} + + //@PDA + /** + * Sets the properties based on ";" delimited string of properties, in same + * fashion as URL properties specified with + * DriverManager.getConnection(urlProperties). This method simply parses + * property string and then calls setPropertes(Properties). This method is + * intended as an enhancement so that the user does not have to write new + * code to call the setters for new/deleted properties. + * + * @param propertiesString list of ";" delimited properties + */ + public void setProperties(String propertiesString) + { + //use existing JDDatasourceURL to parse properties string like Connection does + //but first have to add dummy protocol so we can re-use parsing code + propertiesString = "jdbc:as400://dummyhost;" + propertiesString; + JDDataSourceURL dsURL = new JDDataSourceURL(propertiesString); + //returns only properties specified in propertyString.. (none of + // JDProperties defaults) + Properties properties = dsURL.getProperties(); + setProperties(properties); + } + + //@PDA + /** + * Sets the properties for this datasource. This method is intended as an + * enhancement so that the user does not have to write new code to call the + * setters for new/deleted properties. + * + * @param newProperties object containing updated property values + */ + public void setProperties(Properties newProperties) + { + //1. turn on/off tracing per new props + //2. set needed AS400JDBCDataSource instance variables + //3. set socket props + //4. propagate newProperties to existing properties_ object + + // Check first thing to see if the trace property is + // turned on. This way we can trace everything, including + // the important stuff like loading the properties. + + // If trace property was set to true, turn on tracing. If trace property + // was set to false, + // turn off tracing. If trace property was not set, do not change. + if (JDProperties.isTraceSet(newProperties, null) == JDProperties.TRACE_SET_ON) + { + if (!JDTrace.isTraceOn()) + JDTrace.setTraceOn(true); + } else if (JDProperties.isTraceSet(newProperties, null) == JDProperties.TRACE_SET_OFF) + { + if (JDTrace.isTraceOn()) + JDTrace.setTraceOn(false); + } + + // If toolbox trace is set to datastream. Turn on datastream tracing. + if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_DATASTREAM) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceDatastreamOn(true); + } + // If toolbox trace is set to diagnostic. Turn on diagnostic tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceDiagnosticOn(true); + } + // If toolbox trace is set to error. Turn on error tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_ERROR) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceErrorOn(true); + } + // If toolbox trace is set to information. Turn on information tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_INFORMATION) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceInformationOn(true); + } + // If toolbox trace is set to warning. Turn on warning tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_WARNING) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceWarningOn(true); + } + // If toolbox trace is set to conversion. Turn on conversion tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_CONVERSION) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceConversionOn(true); + } + // If toolbox trace is set to proxy. Turn on proxy tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_PROXY) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceProxyOn(true); + } + // If toolbox trace is set to pcml. Turn on pcml tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_PCML) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTracePCMLOn(true); + } + // If toolbox trace is set to jdbc. Turn on jdbc tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_JDBC) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceJDBCOn(true); + } + // If toolbox trace is set to all. Turn on tracing for all categories. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_ALL) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceAllOn(true); + } + // If toolbox trace is set to thread. Turn on thread tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_THREAD) + { + if (!Trace.isTraceOn()) + { + Trace.setTraceOn(true); + } + Trace.setTraceThreadOn(true); + } + // If toolbox trace is set to none. Turn off tracing. + else if (JDProperties.isToolboxTraceSet(newProperties, null) == JDProperties.TRACE_TOOLBOX_NONE) + { + if (Trace.isTraceOn()) + { + Trace.setTraceOn(false); + } + } + + //next we need to set instance vars (via setX() methods) + //or setup socket properties or set in properties_ + //Note: this is similar to AS400JDBCDataSource(Reference reference)logic + + Enumeration e = newProperties.keys(); + while (e.hasMoreElements()) + { + String propertyName = (String) e.nextElement(); + String propertyValue = (String) newProperties.getProperty(propertyName); + + int propIndex = JDProperties.getPropertyIndex(propertyName); + + //some of the setter methods also set the properties_ below + if (propIndex == JDProperties.DATABASE_NAME) + setDatabaseName(propertyValue); + else if (propIndex == JDProperties.USER) + setUser(propertyValue); + else if (propIndex == JDProperties.PASSWORD) + setPassword(properties_.getString(JDProperties.PASSWORD)); + else if (propIndex == JDProperties.SECURE) + setSecure(propertyValue.equals(TRUE_) ? true : false); + else if (propIndex == JDProperties.KEEP_ALIVE) + setKeepAlive(propertyValue.equals(TRUE_) ? true : false); + else if (propIndex == JDProperties.RECEIVE_BUFFER_SIZE) + setReceiveBufferSize(Integer.parseInt(propertyValue)); + else if (propIndex == JDProperties.SEND_BUFFER_SIZE) + setSendBufferSize(Integer.parseInt(propertyValue)); + else if (propIndex == JDProperties.PROMPT) + setPrompt(propertyValue.equals(TRUE_) ? true : false); + else if (propIndex == JDProperties.KEY_RING_NAME){ + //at this time, decided to not allow this due to security and fact that there is no setKeyRingName() method + if (JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Property: " + propertyName + " can only be changed in AS400JDBCDataSource constructor"); + } else if (propIndex == JDProperties.KEY_RING_PASSWORD){ + //at this time, decided to not allow this due to security and fact that there is no setKeyRingPassword() method + if (JDTrace.isTraceOn()) + JDTrace.logInformation(this, "Property: " + propertyName + " can only be changed in AS400JDBCDataSource constructor"); + } else if (propIndex != -1) + { + properties_.setString(propIndex, propertyValue); + } + } + + } + + /** + * Sets the name of the proxy server. + * @param proxyServer The proxy server. + **/ + public void setProxyServer(String proxyServer) + { + String property = "proxyServer"; + if (proxyServer == null) + throw new NullPointerException(property); + + String old = getProxyServer(); + properties_.setString(JDProperties.PROXY_SERVER, proxyServer); + + changes_.firePropertyChange(property, old, proxyServer); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + proxyServer); //@A8C + } + + /** + * Sets the source of the text for REMARKS columns in ResultSets returned + * by DatabaseMetaData methods. + * @param remarks The text source. + * Valid values include: "sql" (SQL object comment) and "system" (IBM i object description). + * The default value is "system". + **/ + public void setRemarks(String remarks) + { + String property = "remarks"; + if (remarks == null) + throw new NullPointerException("remarks"); + validateProperty(property, remarks, JDProperties.REMARKS); + + String old = getRemarks(); + properties_.setString(JDProperties.REMARKS, remarks); + + changes_.firePropertyChange(property, old, remarks); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + remarks); //@A8C + } + + //@K94 + /** + * Sets whether the cursor is held after a rollback. + * @param cursorHold true if the cursor is held; false otherwise. The default value is false. + **/ + public void setRollbackCursorHold(boolean cursorHold) + { + String property = "rollbackCursorHold"; + Boolean oldHold = new Boolean(isRollbackCursorHold()); + Boolean newHold = new Boolean(cursorHold); + + if (cursorHold) + properties_.setString(JDProperties.ROLLBACK_CURSOR_HOLD, TRUE_); + else + properties_.setString(JDProperties.ROLLBACK_CURSOR_HOLD, FALSE_); + + changes_.firePropertyChange(property, oldHold, newHold); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + cursorHold); + } + + /** + * Sets the secondary URL to be used for a connection on the middle-tier's + * DriverManager in a multiple tier environment, if it is different than + * already specified. This property allows you to use this driver to connect + * to databases other than DB2 for IBM i. Use a backslash as an escape character + * before backslashes and semicolons in the URL. + * @param url The secondary URL. + **/ + public void setSecondaryUrl(String url) + { + if (url == null) + throw new NullPointerException("url"); + + String old = getSecondaryUrl(); + properties_.setString(JDProperties.SECONDARY_URL, url); + + changes_.firePropertyChange("secondaryUrl", old, url); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "secondaryUrl: " + url); //@A8C + } + + //@dup + /** + * Sets the secondary URL to be used for a connection on the middle-tier's + * DriverManager in a multiple tier environment, if it is different than + * already specified. This property allows you to use this driver to connect + * to databases other than DB2 for IBM i. Use a backslash as an escape character + * before backslashes and semicolons in the URL. + * @param url The secondary URL. + * Note: this method is the same as setSecondaryUrl() so that it corresponds to the connection property name + **/ + public void setSecondaryURL(String url) + { + setSecondaryUrl(url); + } + + /** + * Sets whether a Secure Socket Layer (SSL) connection is used to communicate + * with the IBM i system. SSL connections are only available when connecting to systems + * at V4R4 or later. + * @param secure true if Secure Socket Layer connection is used; false otherwise. + * The default value is false. + **/ + public void setSecure(boolean secure) + { + Boolean oldValue = new Boolean(isSecure()); + Boolean newValue = new Boolean(secure); + + //Do not allow user to change to not secure if they constructed the data source with + //a keyring. + if (!secure && isSecure_) //@C2A + { //@C2A + throw new ExtendedIllegalStateException("secure", + ExtendedIllegalStateException.PROPERTY_NOT_CHANGED); //@C2A + } //@C2A + + // keep away the secure flag // @F0A + isSecure_ = secure; // @F0A + + if (secure) + properties_.setString(JDProperties.SECURE, TRUE_); + else + properties_.setString(JDProperties.SECURE, FALSE_); + + changes_.firePropertyChange("secure", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "secure: " + secure); //@A8C + } + + //@pw3 + /** + * Sets whether to disallow "" and *current as user name and password. + * True indicates to disallow "" and *current for user name and password. + * @param secureCurrentUser The secure current user setting. + **/ + public void setSecureCurrentUser(boolean secureCurrentUser) + { + String property = "secureCurrentUser"; + Boolean oldVal = new Boolean(isSecureCurrentUser()); + Boolean newVal = new Boolean(secureCurrentUser); + + if (secureCurrentUser) + properties_.setString(JDProperties.SECURE_CURRENT_USER, TRUE_); + else + properties_.setString(JDProperties.SECURE_CURRENT_USER, FALSE_); + + changes_.firePropertyChange(property, oldVal, newVal); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + secureCurrentUser); + } + + + /** + * Sets the IBM i system name. + * @param serverName The system name. + **/ + public void setServerName(String serverName) + { + String property = SERVER_NAME; + if (serverName == null) + throw new NullPointerException(property); + + String old = getServerName(); + + // keep away the name to serialize // @F0A + serialServerName_ = serverName; // @F0A + + try + { + as400_.setSystemName(serverName); + } + catch (PropertyVetoException pv) + { /* ignore */ + } + + changes_.firePropertyChange(property, old, serverName); + + logProperty ("server name", as400_.getSystemName()); + } + + + // @j1 new method + /** + * Enables tracing of the JDBC server job. + * If tracing is enabled, tracing is started when + * the client connects to the IBM i system, and ends when the connection + * is disconnected. Tracing must be started before connecting to + * the system since the client enables tracing only at connect time. + * + *

+ * Trace data is collected in spooled files on the system. Multiple + * levels of tracing can be turned on in combination by adding + * the constants and passing that sum on the set method. For example, + *

+    *  dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+    *  
+ * @param traceCategories level of tracing to start. + *

Valid values include: + *

+ *

+ * Tracing the JDBC server job will use significant amounts of system resources. + * Additional processor resource is used to collect the data, and additional + * storage is used to save the data. Turn on tracing only to debug + * a problem as directed by IBM service. + * + * + **/ + public void setServerTraceCategories(int traceCategories) + { + String property = "serverTrace"; + + Integer oldValue = new Integer(getServerTraceCategories()); + Integer newValue = new Integer(traceCategories); + + properties_.setString(JDProperties.TRACE_SERVER, newValue.toString()); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + traceCategories); + } + + //@dup + /** + * Enables tracing of the JDBC server job. + * If tracing is enabled, tracing is started when + * the client connects to the IBM i system, and ends when the connection + * is disconnected. Tracing must be started before connecting to + * the system since the client enables tracing only at connect time. + * + *

+ * Trace data is collected in spooled files on the system. Multiple + * levels of tracing can be turned on in combination by adding + * the constants and passing that sum on the set method. For example, + *

+     *  dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+     *  
+ * @param traceCategories level of tracing to start. + *

Valid values include: + *

+ *

+ * Tracing the JDBC server job will use significant amounts of system resources. + * Additional processor resource is used to collect the data, and additional + * storage is used to save the data. Turn on tracing only to debug + * a problem as directed by IBM service. + * + * Note: this method is the same as setServerTraceCategories() so that it corresponds to the connection property name + **/ + public void setServerTrace(int traceCategories) + { + setServerTraceCategories(traceCategories); + } + + + // @A2A + /** + * Sets the JDBC driver implementation. + * This property has no + * effect if the "secondary URL" property is set. + * This property cannot be set to "native" if the + * environment is not an IBM i Java Virtual Machine. + * param driver The driver value. + *

Valid values include: + *

+ * The default value is "toolbox". + * Note: Not supported in a connection pool. + **/ + public void setDriver(String driver) + { + String property = "driver"; + if (driver == null) + throw new NullPointerException(property); + + validateProperty(property, driver, JDProperties.DRIVER); + String old = getDriver(); + + properties_.setString(JDProperties.DRIVER, driver); + + changes_.firePropertyChange(property, old, driver); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + driver); //@A8C + } + + // @J3 new method + /** + * Sets whether to save the password locally with the rest of the properties when + * this data source object is serialized. + *

+ * If the password is saved, it is up to the application to protect + * the serialized form of the object because it contains all necessary + * information to connect to the IBM i system. The default is false. It + * is a security risk to save the password with the rest of the + * properties so by default the password is not saved. If the application + * programmer chooses to accept this risk, set this property to true + * to force the Toolbox to save the password with the other properties + * when the data source object is serialized. + * + * @param savePassword true if the password is saved; false otherwise. + * The default value is false + **/ + public void setSavePasswordWhenSerialized(boolean savePassword) + { + String property = "savePasswordWhenSerialized"; //@C5A + + boolean oldValue = isSavePasswordWhenSerialized(); //@C5A + boolean newValue = savePassword; //@C5A + + savePasswordWhenSerialized_ = savePassword; + + changes_.firePropertyChange(property, oldValue, newValue); //@C5A + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, "save password: " + savePassword); + } + + + /** + * Sets the three-character language id to use for selection of a sort sequence. + * This property has no effect unless the sort property is set to "language". + * @param language The three-character language id. + * The default value is ENU. + **/ + public void setSortLanguage(String language) + { + if (language == null) + throw new NullPointerException("language"); + + String old = getSortLanguage(); + properties_.setString(JDProperties.SORT_LANGUAGE, language); + + changes_.firePropertyChange("sortLanguage", old, language); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "sortLanguage: " + language); //@A8C + } + + /** + * Sets the library and file name of a sort sequence table stored on the + * IBM i system. + * This property has no effect unless the sort property is set to "table". + * The default is an empty String (""). + * @param table The qualified sort table name. + **/ + public void setSortTable(String table) + { + if (table == null) + throw new NullPointerException("table"); + + String old = getSortTable(); + properties_.setString(JDProperties.SORT_TABLE, table); + + changes_.firePropertyChange("sortTable", old, table); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "sortTable: " + table); //@A8C + } + + /** + * Sets how the IBM i system treats case while sorting records. This property + * has no effect unless the sort property is set to "language". + * @param sortWeight The sort weight. + * Valid values include: "shared" (upper- and lower-case characters are sorted as the + * same character) and "unique" (upper- and lower-case characters are sorted as + * different characters). The default value is "shared". + **/ + public void setSortWeight(String sortWeight) + { + String property = "sortWeight"; + if (sortWeight == null) + throw new NullPointerException(property); + + validateProperty(property, sortWeight, JDProperties.SORT_WEIGHT); + + String old = getSortWeight(); + properties_.setString(JDProperties.SORT_WEIGHT, sortWeight); + + changes_.firePropertyChange(property, old, sortWeight); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + sortWeight); //@A8C + } + + /** + * Sets whether a thread is used. + * @param threadUsed true if a thread is used; false otherwise. + * The default value is true. + **/ + public void setThreadUsed(boolean threadUsed) + { + Boolean oldValue = new Boolean(isThreadUsed()); + Boolean newValue = new Boolean(threadUsed); + + if (threadUsed) + properties_.setString(JDProperties.THREAD_USED, TRUE_); + else + properties_.setString(JDProperties.THREAD_USED, FALSE_); + + try + { + as400_.setThreadUsed(threadUsed); + } + catch (PropertyVetoException pve) + { /* Will never happen */ + } + + changes_.firePropertyChange("threadUsed", oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "threadUsed: " + threadUsed); //@A8C + } + + /** + * Sets the time format used in time literals with SQL statements. + * @param timeFormat The time format. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public void setTimeFormat(String timeFormat) + { + String property = "timeFormat"; + if (timeFormat == null) + throw new NullPointerException(property); + validateProperty(property, timeFormat, JDProperties.TIME_FORMAT); + + String old = getTimeFormat(); + properties_.setString(JDProperties.TIME_FORMAT, timeFormat); + + changes_.firePropertyChange(property, old, timeFormat); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + timeFormat); //@A8C + } + + /** + * Sets the time separator used in time literals within SQL statements. + * This property has no effect unless the time format property is set to "hms". + * @param timeSeparator The time separator. + *

Valid values include: + *

+ * The default value is based on the server job. + **/ + public void setTimeSeparator(String timeSeparator) + { + String property = "timeSeparator"; + if (timeSeparator == null) + throw new NullPointerException(property); + validateProperty(property, timeSeparator, JDProperties.TIME_SEPARATOR); + + String old = getTimeSeparator(); + properties_.setString(JDProperties.TIME_SEPARATOR, timeSeparator); + + changes_.firePropertyChange(property, old, timeSeparator); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + timeSeparator); //@A8C + } + + /** + * Sets whether trace messages should be logged. Trace messages are + * useful for debugging programs that call JDBC. However, there is a + * performance penalty associated with logging trace messages, so this + * property should only be set to true for debugging. Trace messages + * are logged to System.out. + * @param trace true if trace message are logged; false otherwise. + * The default value is false. + **/ + public void setTrace(boolean trace) + { + Boolean oldValue = new Boolean(isTrace()); + Boolean newValue = new Boolean(trace); + + if (trace) + properties_.setString(JDProperties.TRACE, TRUE_); + else + properties_.setString(JDProperties.TRACE, FALSE_); + + changes_.firePropertyChange("trace", oldValue, newValue); + + if (trace) + { + if (!JDTrace.isTraceOn ()) + JDTrace.setTraceOn (true); + } + else + JDTrace.setTraceOn (false); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, "trace: " + trace); //@A8C + } + + + /** + * Sets the IBM i system's transaction isolation. + * @param transactionIsolation The transaction isolation level. + *

Valid values include: + *

+ **/ + public void setTransactionIsolation(String transactionIsolation) + { + String property = "transactionIsolation"; + + if (transactionIsolation == null) + throw new NullPointerException(property); + validateProperty(property, transactionIsolation, JDProperties.TRANSACTION_ISOLATION); + + String old = getTransactionIsolation(); + + properties_.setString(JDProperties.TRANSACTION_ISOLATION, transactionIsolation); + + changes_.firePropertyChange(property, old, transactionIsolation); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + transactionIsolation); //@A8C + } + + /** + * Sets whether binary data is translated. If this property is set + * to true, then BINARY and VARBINARY fields are treated as CHAR and + * VARCHAR fields. + * @param translate true if binary data is translated; false otherwise. + * The default value is false. + **/ + public void setTranslateBinary(boolean translate) + { + String property = "translateBinary"; + + Boolean oldValue = new Boolean(isTranslateBinary()); + Boolean newValue = new Boolean(translate); + + if (translate) + properties_.setString(JDProperties.TRANSLATE_BINARY, TRUE_); + else + properties_.setString(JDProperties.TRANSLATE_BINARY, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) //@A8C + JDTrace.logInformation (this, property + ": " + translate); //@A8C + } + + //@PDA + /** + * Sets how Boolean objects are interpreted when setting the value + * for a character field/parameter using the PreparedStatement.setObject(), + * CallableStatement.setObject() or ResultSet.updateObject() methods. Setting the + * property to "true", would store the Boolean object in the character field as either + * "true" or "false". Setting the property to "false", would store the Boolean object + * in the character field as either "1" or "0". + * @param translate true if boolean data is translated; false otherwise. + * The default value is true. + **/ + public void setTranslateBoolean(boolean translate) + { + String property = "translateBoolean"; + + Boolean oldValue = new Boolean(isTranslateBoolean()); + Boolean newValue = new Boolean(translate); + + if (translate) + properties_.setString(JDProperties.TRANSLATE_BOOLEAN, TRUE_); + else + properties_.setString(JDProperties.TRANSLATE_BOOLEAN, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + translate); + } + + + /** + * Indicates whether blocking should be used for updates and delete. + * @param value true if blocking is used for updates and deletes. + * The default value is false. + **/ + public void setUseBlockUpdate(boolean value) + { + String property = JDProperties.DO_UPDATE_DELETE_BLOCKING_ ; + Boolean oldValue = new Boolean(isUseBlockUpdate()); + Boolean newValue = new Boolean(value); + + if (value) + properties_.setString(JDProperties.DO_UPDATE_DELETE_BLOCKING, TRUE_); + else + properties_.setString(JDProperties.DO_UPDATE_DELETE_BLOCKING, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + value); + } + + + /** + * Sets the database user. + * @param user The user. + **/ + public void setUser(String user) + { + String property = "user"; + + String old = getUser(); + + // save away the user to serialize // @F0A + serialUserName_ = user; // @F0A + + try + { + as400_.setUserId(user); + } + catch (PropertyVetoException vp) + { /* ignore */ + } + + changes_.firePropertyChange(property, old, user); + + logProperty ("user", as400_.getUserId()); + } + + //@K54 + /** + * Specifies whether variable-length fields should be compressed. + * @param compress true if variable-length fields should be compressed; false otherwise. + * The default value is true. + **/ + public void setVariableFieldCompression(boolean compress) + { + String property = "variableFieldCompression"; + + Boolean oldValue = new Boolean(isVariableFieldCompression()); + Boolean newValue = new Boolean(compress); + + if (compress) + properties_.setString(JDProperties.VARIABLE_FIELD_COMPRESSION, TRUE_); + else + properties_.setString(JDProperties.VARIABLE_FIELD_COMPRESSION, FALSE_); + + changes_.firePropertyChange(property, oldValue, newValue); + + if (JDTrace.isTraceOn()) + JDTrace.logInformation (this, property + ": " + compress); + } + + + /** + * Specifies how variable-length fields should be compressed. + * @param compress Possible values are + *