diff --git a/jdbc40/.classpath b/jdbc40/.classpath
new file mode 100644
index 000000000..f8367783f
--- /dev/null
+++ b/jdbc40/.classpath
@@ -0,0 +1,8 @@
+
+
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: +
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
+ * For the fixed-length type JDBC
+ * For the fixed-length type JDBC 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 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 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 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
+ * 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * 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:
+ 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:
+ 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:
+ 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:
+ 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; j 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:
+ 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:
+ 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:
+ 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.
+ * JDBC and DB2 for IBM i use different terminology for transaction
+ isolation levels. The following table provides a terminology
+ mapping:
+
+ 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
+ * 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
+ * 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
+ * If an error occurs in setting any of the client info properties, a
+ *
+ *
+ * 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
+ * Applications may use the
+ *
+ * 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
+ * @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
+ * 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 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.
+* 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:
+ * 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:
+ 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:
+ * 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:
+ 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:
+ * 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:
+ 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:
+ 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:
+ * 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.
+ * JDBC and DB2 for IBM i use different terminology for transaction
+ * isolation levels. The following table provides a terminology
+ * mapping:
+ *
+ * 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
+ *
+ * If an error occurs in setting any of the client info properties, a
+ *
+ * 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
+ * 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
+ * @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
+ * Applications may use the
+ * 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
+ * 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.
+*
+* The following is an example that creates an AS400JDBCDataSource object and creates a
+* connection to the database.
+*
+* The following example registers an AS400JDBCDataSource object with JNDI and then
+* uses the object returned from JNDI to obtain a database connection.
+* The return value is a combination of the following:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * 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,
+ * 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:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * 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:
+ * Valid values include:
+ *
+ * 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:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ *
+ * 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,
+ * 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,
+ * 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:
+ *
+ * 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:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values are -1 to MAX_STORAGE_LIMIT megabytes.
+ * The default value is -1 meaning there is no limit.
+ **/
+ public void setQueryStorageLimit(int limit)
+ {
+ String property = "queryStorageLimit";
+
+ if (limit < -1 || limit > MAX_STORAGE_LIMIT)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+
+ Integer oldValue = new Integer(getQueryStorageLimit());
+ Integer newValue = new Integer(limit);
+
+ properties_.setString(JDProperties.QUERY_STORAGE_LIMIT, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + limit);
+ }
+
+ /*@D4A*/
+ /**
+ * Sets the query timeout mechanism property, which indicates how
+ * the toolbox will enforce the query timeout specified on the statement.
+ * @param timeoutMechanism The timeout mechanism to use.
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Valid values include:
+ * Some of the methods in this class take arguments that are
+pattern strings. Such arguments are suffixed with "Pattern".
+Within a pattern string, "%" means match any substring of zero
+or more characters, and "_" means match exactly one character.
+Only entries matching the pattern string are returned.
+
+ For example, if the schemaPattern argument for getTables()
+is "H%WO_LD", then the following schemas might match
+the pattern, provided they exist on the system:
+ Many of the methods here return lists of information in
+result sets. You can use the normal ResultSet methods to
+retrieve data from these result sets. The format of the
+result sets are described in the JDBC interface specification.
+
+ Schema and table names that are passed as input to methods
+in this class are implicitly uppercased unless enclosed in
+double-quotes.
+**/
+
+//-----------------------------------------------------------
+// Using nulls and empty strings for catalog functions
+//
+// When the parameter is NOT search pattern capable and:
+// null is specified for:
+// catalog (system) - parameter is ignored
+// schema (library) - use default SQL schema
+// The default SQL schema can be
+// set in the URL. If not
+// specified in URL, the first
+// library specified in the library
+// properties is used as the
+// default SQL schema.
+// If no default SQL schema exists,
+// QGPL is used.
+// table (file) - empty result set is returned
+// column (field) - empty result set is returned
+// empty string is specified for:
+// catalog (system) - empty result set is returned
+// schema (library) - empty result set is returned
+// table (file) - empty result set is returned
+// column (field) - empty result set is returned
+//
+//
+// When the parameter is search pattern capable and:
+// null is specified for:
+// schemaPattern (library) - no value sent to system.
+// System default of
+// *USRLIBL is used.
+// tablePattern (file) - no value sent to system
+// system default of *ALL used
+// empty string is specified for:
+// schemaPattern (library) - empty result set is returned
+// tablePattern (file) - empty result set is returned
+//
+//
+//----------------------------------------------------------
+
+public class AS400JDBCDatabaseMetaData
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+
+implements DatabaseMetaData
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+
+ //New constants for JDBC 3.0.
+ public static final int sqlStateXOpen = 1;
+ public static final int sqlStateSQL99 = 2;
+
+
+ // Private data.
+ private AS400JDBCConnection connection_;
+ private int id_;
+ private SQLConversionSettings settings_;
+
+ //@mdsp misc constants for sysibm stored procedures
+ final static int SQL_NO_NULLS = 0; //@mdsp
+ final static int SQL_NULLABLE = 1; //@mdsp
+ final static int SQL_NULLABLE_UNKNOWN = 2; //@mdsp
+ final static int SQL_BEST_ROWID = 1; //@mdsp
+ final static int SQL_ROWVER = 2; //@mdsp
+ static final String EMPTY_STRING = ""; //@mdsp
+ static final String MATCH_ALL = "%"; //@mdsp
+
+
+ private static final String VIEW = "VIEW"; //@mdsp
+ private static final String TABLE = "TABLE"; //@mdsp
+ private static final String SYSTEM_TABLE = "SYSTEM TABLE"; //@mdsp
+ private static final String ALIAS = "ALIAS"; //@mdsp
+ private static final String MQT = "MATERIALIZED QUERY TABLE"; //@mdsp
+ private static final String SYNONYM = "SYNONYM"; //@mdsp
+ private static final String FAKE_VALUE = "QCUJOFAKE"; //@mdsp
+ private static final int SQL_ALL_TYPES = 0; //@mdsp
+
+ // the DB2 SQL reference says this should be 2147483647 but we return 1 less to allow for NOT NULL columns
+ static final int MAX_LOB_LENGTH = 2147483646; //@xml3
+
+
+ static int javaVersion = 0;
+ static {
+ String javaVersionString = System.getProperty("java.version");
+ if (javaVersionString != null) {
+ int dotIndex = javaVersionString.indexOf('.');
+ if (dotIndex > 0) {
+ int secondDotIndex = javaVersionString.indexOf('.', dotIndex+1);
+ if (secondDotIndex > 0) {
+ String firstDigit = javaVersionString.substring(0,dotIndex);
+ String secondDigit = javaVersionString.substring(dotIndex+1, secondDotIndex);
+ javaVersion = Integer.parseInt(firstDigit)*10 + Integer.parseInt(secondDigit);
+ }
+ } else {
+ // Android return 0. Set as version 4. @G3A
+ if ("0".equals(javaVersionString)) {
+ javaVersion = 4;
+ }
+ }
+ }
+ }
+
+ /**
+ Constructs an AS400JDBCDatabaseMetaData object.
+
+ @param connection The connection to the system.
+ @param id The ID the caller has assigned to this
+ AS400JDBCDatabaseMetaData.
+ **/
+ AS400JDBCDatabaseMetaData (AS400JDBCConnection connection, int id)
+ throws SQLException
+ {
+ connection_ = connection;
+ settings_ = SQLConversionSettings.getConversionSettings(connection);
+ id_ = id;
+ }
+
+
+
+ /**
+ Indicates if all of the procedures returned by getProcedures() can be
+ called by the current user.
+
+ @return Always false. This driver cannot determine if all of the procedures
+ can be called by the current user.
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean allProceduresAreCallable ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if all of the tables returned by getTables() can be
+ SELECTed by the current user.
+
+ @return Always false. This driver cannot determine if all of the tables
+ returned by getTables() can be selected by the current user.
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean allTablesAreSelectable ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a data definition statement within a transaction
+ can force the transaction to commit.
+
+ @return Always false. A data definition statement within a transaction
+ does not force the transaction to commit.
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean dataDefinitionCausesTransactionCommit ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a data definition statement within a transaction is
+ ignored.
+
+ @return Always false. A data definition statement within a
+ transaction is not ignored.
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean dataDefinitionIgnoredInTransactions ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if visible deletes to a result set of the specified type
+ can be detected by calling ResultSet.rowDeleted(). If visible
+ deletes cannot be detected, then rows are removed from the
+ result set as they are deleted.
+
+ @param resultSetType The result set type. Value values are:
+ Note: For this function to work with procedure names
+ longer than 10 characters, the metadata source=1 property must be used on the connection.
+ This is the default when connecting to a V7R1 or later system.
+
+
+ @param catalog The catalog name. If null is specified, this parameter
+ is ignored. If empty string is specified,
+ an empty result set is returned.
+ @param schemaPattern The schema name pattern. If null is specified,
+ it will not be included in the selection
+ criteria. If empty string
+ is specified, an empty result set is returned.
+ @param procedurePattern The procedure name pattern. If null is specified,
+ it will not be included in the selection criteria.
+ If empty string
+ is specified, an empty result set is returned.
+ @param columnPattern The column name pattern. If null is specified,
+ it will not be included in the selection criteria.
+ If empty string
+ is specified, an empty result set is returned.
+
+ @return The ResultSet containing the description of the
+ catalog's stored procedure parameters and result
+ columns.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getProcedureColumns (String catalog,
+ String schemaPattern,
+ String procedurePattern,
+ String columnPattern)
+ throws SQLException
+ {
+ connection_.checkOpen ();
+ int vrm = connection_.getVRM(); //@trunc3
+
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLPROCEDURECOLS(?,?,?,?,?)");
+
+ cs.setString(1, normalize(catalog));
+ cs.setString(2, normalize(schemaPattern));
+ cs.setString(3, normalize(procedurePattern));
+ cs.setString(4, normalize(columnPattern));
+/* ifdef JDBC40 */
+ cs.setString(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@ver4
+/* endif */
+/* ifndef JDBC40
+ cs.setString(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
+ endif */
+ cs.execute();
+
+ ResultSet rs = cs.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cs.close(); //@mdrs2
+
+ return rs; //@mdrs
+
+ }
+
+ //--------------------------------------------------------
+ // Set up the result set in the format required by JDBC
+ //--------------------------------------------------------
+
+ String[] fieldNames = { "PROCEDURE_CAT",
+ "PROCEDURE_SCHEM",
+ "PROCEDURE_NAME",
+ "COLUMN_NAME",
+ "COLUMN_TYPE",
+ "DATA_TYPE",
+ "TYPE_NAME",
+ "PRECISION",
+ "LENGTH",
+ "SCALE",
+ "RADIX",
+ "NULLABLE",
+ "REMARKS"
+ };
+
+ SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog
+ new SQLVarchar (128, settings_), // schema
+ new SQLVarchar (128, settings_), // procedure
+ new SQLVarchar (128, settings_), // column name
+ new SQLSmallint (vrm, settings_), // column type //@trunc3
+ new SQLSmallint (vrm, settings_), // data type //@trunc3
+ new SQLVarchar (128, settings_), // type name
+ new SQLInteger (vrm, settings_), // precision //@trunc3
+ new SQLInteger (vrm, settings_), // length //@trunc3
+ new SQLSmallint (vrm, settings_), // scale //@trunc3
+ new SQLInteger (vrm, settings_), // radix //@trunc3
+ new SQLSmallint (vrm, settings_), // nullable //@trunc3
+ new SQLVarchar (2000, settings_) // remarks
+ };
+
+ int[] fieldNullables = {
+ columnNullable, // catalog
+ columnNullable, // schema
+ columnNoNulls, // Procedure name
+ columnNoNulls, // column name
+ columnNoNulls, // column type
+ columnNoNulls, // data type
+ columnNoNulls, // type name
+ columnNoNulls, // precision
+ columnNoNulls, // length
+ columnNoNulls, // scale
+ columnNoNulls, // radix
+ columnNoNulls, // nullable
+ columnNoNulls // remarks
+ };
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+
+ JDRowCache rowCache = null;
+ try
+ {
+ // Check for conditions that would result in an empty result set
+ // Must check for null first to avoid NullPointerException
+
+ if ((!isCatalogValid(catalog)) || // catalog is empty string
+
+ // schema is not null and is empty string
+ ((schemaPattern != null) && (schemaPattern.length()==0)) ||
+
+ // procedure is not null and is empty string
+ ((procedurePattern != null) && (procedurePattern.length()==0)) ||
+
+ // column is not null and is empty string
+ ((columnPattern != null) && (columnPattern.length()==0)))
+ { // Return empty result set
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+ else
+
+ { // Parameters are valid, build request and send
+ StringBuffer selectStmt = new StringBuffer();
+ selectStmt.append ("SELECT SPECIFIC_SCHEMA, SPECIFIC_NAME, PARAMETER_NAME, PARAMETER_MODE, ");
+ selectStmt.append ("DATA_TYPE, NUMERIC_PRECISION, CHARACTER_MAXIMUM_LENGTH, NUMERIC_SCALE, ");
+ selectStmt.append ("NUMERIC_PRECISION_RADIX, IS_NULLABLE, LONG_COMMENT ");
+ selectStmt.append ("FROM QSYS2" + getCatalogSeparator() + "SYSPARMS "); // use . or /
+
+
+
+
+ if (schemaPattern !=null)
+ {
+ JDSearchPattern schema = new JDSearchPattern (normalize(schemaPattern)); //@pdc normalize
+ String schemaWhereClause = schema.getSQLWhereClause("SPECIFIC_SCHEMA");
+ selectStmt.append("WHERE " + schemaWhereClause);
+ }
+
+
+ if (procedurePattern !=null)
+ {
+ JDSearchPattern procedure = new JDSearchPattern (procedurePattern);
+ if (schemaPattern!=null)
+ { // Where clause already exists, add AND
+ selectStmt.append (" AND ");
+ }
+
+ else
+ { // Where clause does not exist, add WHERE
+ selectStmt.append (" WHERE ");
+ }
+
+ String procedureWhereClause = procedure.getSQLWhereClause("SPECIFIC_NAME");
+ selectStmt.append(procedureWhereClause);
+ }
+
+
+ if (columnPattern!=null)
+ { // if null, no where clause is sent
+ JDSearchPattern column = new JDSearchPattern (columnPattern);
+ if ((schemaPattern!=null) || (procedurePattern!=null))
+ { // Where clause already exists, add AND
+ selectStmt.append (" AND ");
+ }
+ else
+ { // Where clause does not exist, add WHERE
+ selectStmt.append (" WHERE ");
+ }
+
+ String columnWhereClause = column.getSQLWhereClause("PARAMETER_NAME");
+ selectStmt.append(columnWhereClause);
+
+ }
+
+
+
+
+ // Add order by
+ selectStmt.append ("ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION"); // Added ORDINAL_POSITION to fix JTOpen bug 3646, SYSPARMS table doesn't always have parameters in physical right order
+
+ // Create statement object and do Execute Query
+ AS400JDBCStatement statement_ = null; //@scan1
+ AS400JDBCResultSet serverResultSet = null; //@scan1
+ JDRowCache serverRowCache = null;
+ try
+ {
+ statement_ = (AS400JDBCStatement)connection_.createStatement(); // caste needed
+ serverResultSet = (AS400JDBCResultSet) statement_.executeQuery (selectStmt.toString());
+
+ serverRowCache = new JDSimpleRowCache(serverResultSet.getRowCache());
+
+
+ JDFieldMap[] maps = new JDFieldMap[13];
+
+ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog());
+ maps[1] = new JDSimpleFieldMap (1); // schema
+ maps[2] = new JDSimpleFieldMap (2); // procedure
+ maps[3] = new JDHandleNullFieldMap (3, ""); // parameter name (col name)
+ maps[4] = new JDParameterModeFieldMap(4); // Parameter mode (col type)
+
+ maps[5] = new JDDataTypeFieldMap(5, 7, 6, 8, 0, connection_.getVRM(), connection_.getProperties()); // @M0C // data type - converts from string to short //@KKB pass 0 for ccsid
+ maps[6] = new JDSimpleFieldMap (5); // type name
+
+ maps[7] = new JDHandleNullFieldMap (6, new Integer (0)); // precision
+ maps[8] = new JDHandleNullFieldMap (7, new Integer (0)); // length
+
+ maps[9] = new JDHandleNullFieldMap (8, new Short ((short) 0)); // scale
+ maps[10] = new JDHandleNullFieldMap (9, new Short ((short) 0)); // radix
+
+ maps[11] = new JDNullableSmallintFieldMap(10); // nullable - is Nullable
+ maps[12] = new JDHandleNullFieldMap (11, ""); // remarks - long comment
+
+ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
+ rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
+
+ }finally //@scan1
+ {
+ try{
+ if(serverResultSet != null)
+ serverResultSet.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "getProcedureColumns serverResultSet.close()", e);
+ } //allow next close to execute
+ if(statement_ != null)
+ statement_.close ();
+ }
+ } // End of else build request and send
+
+
+ } // End of try block
+
+ catch (SQLException e)
+ {
+ // System.out.println(e);
+ JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
+ }
+
+
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(),
+ "ProcedureColumns", connection_, null); //@in2
+
+ } // End of getProcedureColumns
+
+
+
+ /**
+ Returns the description of the stored procedures available
+ in a catalog.
+
+ @param catalog The catalog name. If null is specified, this parameter
+ is ignored. If empty string is specified,
+ an empty result set is returned.
+ @param schemaPattern The schema name pattern. If null is specified,
+ it will not be included in the selection
+ criteria. If empty string
+ is specified, an empty result set is returned.
+ @param procedurePattern The procedure name pattern. If null is specified,
+ it will not be included in the selection
+ criteria. If empty string
+ is specified, an empty result set is returned.
+
+ @return The ResultSet containing the description of the
+ stored procedures available in the catalog.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getProcedures (String catalog,
+ String schemaPattern,
+ String procedurePattern)
+ throws SQLException
+ {
+ connection_.checkOpen ();
+ int vrm = connection_.getVRM(); //@trunc3
+
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLPROCEDURES(?,?,?,?)");
+
+ cs.setString(1, normalize(catalog));
+ cs.setString(2, normalize(schemaPattern));
+ cs.setString(3, normalize(procedurePattern));
+ cs.setString(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
+ cs.execute();
+
+ ResultSet rs = cs.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cs.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+ //--------------------------------------------------------
+ // Set up the result set in the format required by JDBC
+ //--------------------------------------------------------
+
+ String[] fieldNames = { "PROCEDURE_CAT",
+ "PROCEDURE_SCHEM",
+ "PROCEDURE_NAME",
+ "RESERVED1",
+ "RESERVED2",
+ "RESERVED3",
+ "REMARKS",
+/* ifdef JDBC40 */
+ "PROCEDURE_TYPE",
+ "SPECIFIC_NAME" //@JDBC40
+/* endif */
+/* ifndef JDBC40
+ "PROCEDURE_TYPE"
+ endif */
+ };
+
+ SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog
+ new SQLVarchar (128, settings_), // schema
+ new SQLVarchar (128, settings_), // procedure
+ new SQLInteger (vrm,settings_), // reserved //@trunc3
+ new SQLInteger (vrm,settings_), // reserved //@trunc3
+ new SQLInteger (vrm,settings_), // reserved //@trunc3
+ new SQLVarchar (2000, settings_), // remarks
+/* ifdef JDBC40 */
+ new SQLSmallint (vrm, settings_), // procedure type //@trunc3
+ new SQLVarchar (128, settings_) // specific name //@JDBC40
+
+/* endif */
+/* ifndef JDBC40
+ new SQLSmallint (vrm, settings_) // procedure type //@trunc3
+ endif */
+ };
+
+ int[] fieldNullables = {
+ columnNullable, // Procedure catalog
+ columnNullable, // Procedure schema
+ columnNoNulls, // Procedure name
+ columnNullable, // Reserved 1
+ columnNullable, // Reserved 2
+ columnNullable, // Reserved 3
+ columnNoNulls, // Remarks
+/* ifdef JDBC40 */
+ columnNoNulls, // Procedure type
+ columnNoNulls // Specific name //@JDBC40
+/* endif */
+/* ifndef JDBC40
+ columnNoNulls // Procedure type
+ endif */
+ };
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+
+ JDRowCache rowCache = null;
+ try
+ {
+ // Check for conditions that would result in an empty result set
+ // Must check for null first to avoid NullPointerException
+
+ if ((!isCatalogValid(catalog)) || // catalog is empty string
+
+ // schema is not null and is empty string
+ ((schemaPattern != null) && (schemaPattern.length()==0)) ||
+
+ // procedure is not null and is empty string
+ ((procedurePattern!=null) && (procedurePattern.length()==0)))
+ { // Return empty result set
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+ else
+ { // Parameters are valid, build request and send
+ StringBuffer selectStmt = new StringBuffer();
+/* ifdef JDBC40 */
+ selectStmt.append ("SELECT ROUTINE_SCHEMA, ROUTINE_NAME, REMARKS, RESULTS, SPECIFIC_NAME ");//@PROC //@JDBC40
+/* endif */
+/* ifndef JDBC40
+ selectStmt.append ("SELECT ROUTINE_SCHEMA, ROUTINE_NAME, REMARKS, RESULTS ");//@PROC
+ endif */
+ selectStmt.append ("FROM QSYS2" + getCatalogSeparator() + "SYSPROCS "); // use . or /
+
+
+
+ if (schemaPattern !=null)
+ {
+ JDSearchPattern schema = new JDSearchPattern (schemaPattern);
+ String schemaWhereClause = schema.getSQLWhereClause("ROUTINE_SCHEMA");//@PROC
+ selectStmt.append("WHERE " + schemaWhereClause);
+ }
+
+
+ if (procedurePattern !=null)
+ {
+ JDSearchPattern procedure = new JDSearchPattern (procedurePattern);
+ if (schemaPattern!=null)
+ { // Where clause already exists, add AND
+ selectStmt.append (" AND ");
+ }
+
+ else
+ { // Where clause does not exist, add WHERE
+ selectStmt.append (" WHERE ");
+ }
+
+ String procedureWhereClause = procedure.getSQLWhereClause("ROUTINE_NAME");//@PROC
+ selectStmt.append(procedureWhereClause);
+ }
+
+
+
+ // Add order by
+ selectStmt.append (" ORDER BY ROUTINE_SCHEMA, ROUTINE_NAME");//@PROC
+
+
+ // Create statement object and do Execute Query
+ AS400JDBCStatement statement_ = (AS400JDBCStatement)connection_.createStatement(); // caste needed
+
+ AS400JDBCResultSet serverResultSet = (AS400JDBCResultSet) statement_.executeQuery (selectStmt.toString());
+
+ JDRowCache serverRowCache = new JDSimpleRowCache(serverResultSet.getRowCache());
+ statement_.close ();
+/* ifdef JDBC40 */
+ JDFieldMap[] maps = new JDFieldMap[9];
+/* endif */
+/* ifndef JDBC40
+ JDFieldMap[] maps = new JDFieldMap[8];
+ endif */
+ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog());
+ maps[1] = new JDSimpleFieldMap (1); // schema
+ maps[2] = new JDSimpleFieldMap (2); // procedure
+ maps[3] = new JDHardcodedFieldMap (new Integer (0));
+ maps[4] = new JDHardcodedFieldMap (new Integer (0));
+ maps[5] = new JDHardcodedFieldMap (new Integer (0));
+ maps[6] = new JDHandleNullFieldMap (3, ""); // remarks
+ maps[7] = new JDProcTypeFieldMap (4);
+/* ifdef JDBC40 */
+ maps[8] = new JDSimpleFieldMap (5); //@jdbc40
+/* endif */
+
+ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
+ rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
+
+ } // End of else build request and send
+
+
+ } // End of try block
+
+ catch (SQLException e)
+ {
+ // System.out.println(e);
+ // e.printStackTrace(); // method on throwable object
+ // @B1D JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
+ throw e; // @B1A
+ }
+
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(),
+ "Procedures", connection_, null); //@in2
+
+ }
+
+
+
+ /**
+ Returns the DB2 for IBM i SQL term for "procedure".
+
+ @return The term for "procedure".
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getProcedureTerm ()
+ throws SQLException
+ {
+ return AS400JDBCDriver.getResource ("PROCEDURE_TERM");
+ }
+
+
+
+ //@G4A
+ /**
+ Retrieves the default holdability of this ResultSet object. Holdability is
+ whether ResultSet objects are kept open when the statement is committed.
+
+ @return Always ResultSet.HOLD_CURSORS_OVER_COMMIT.
+
+ @exception SQLException This exception is never thrown.
+
+ @since Modification 5
+ **/
+ public int getResultSetHoldability ()
+ throws SQLException
+ {
+ return AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+
+
+ /**
+ Returns the schema names available in this database.
+ This will return a ResultSet with a list of all the
+ libraries.
+
+ @return The ResultSet containing the list of all the libraries.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getSchemas ()
+ throws SQLException
+ {
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLTABLES(?,?,?,?,?)");
+
+ cs.setString(1, "%");
+ cs.setString(2, "%");
+ cs.setString(3, "%");
+ cs.setString(4, "%");
+ cs.setString(5, "DATATYPE='JDBC';GETSCHEMAS=1;CURSORHOLD=1");
+ cs.execute();
+ ResultSet rs = cs.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cs.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+ return JDUtilities.getLibraries(this, connection_, settings_, false); //@DELIMa
+ }
+
+
+
+ /**
+ Returns the DB2 for IBM i SQL term for "schema".
+
+ @return The term for schema.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getSchemaTerm ()
+ throws SQLException
+ {
+ return AS400JDBCDriver.getResource ("SCHEMA_TERM");
+ }
+
+
+
+ /**
+ Returns the string used to escape wildcard characters.
+ This is the string that can be used to escape '_' or '%'
+ in string patterns.
+
+ @return The escape string.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getSearchStringEscape ()
+ throws SQLException
+ {
+ return JDSearchPattern.getEscape ();
+ }
+
+
+
+ /**
+ Returns the list of all of the database's SQL keywords
+ that are not also SQL92 keywords.
+
+ @return The list of SQL keywords, separated by commas.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getSQLKeywords ()
+ throws SQLException
+ {
+ return "AFTER,ALIAS,ALLOW,APPLICATION,ASSOCIATE,ASUTIME,AUDIT," + // @J2M
+ "AUX,AUXILIARY,BEFORE,BINARY," + // @J2A
+ "BUFFERPOOL,CACHE,CALL,CALLED,CAPTURE,CARDINALITY,CCSID,CLUSTER," + // @J2A
+ "COLLECTION,COLLID,COMMENT,CONCAT,CONDITION,CONTAINS,COUNT_BIG," + // @J2A
+ "CURRENT_LC_CTYPE," + // @J2A
+ "CURRENT_PATH,CURRENT_SERVER,CURRENT_TIMEZONE,CYCLE,DATA," + // @J2A
+ "DATABASE,DAYS," + // @J2A
+ "DB2GENERAL,DB2GENRL,DB2SQL,DBINFO,DEFAULTS,DEFINITION," + // @J2A
+ "DETERMINISTIC," + // @J2A
+ "DISALLOW,DO,DSNHATTR,DSSIZE,DYNAMIC,EACH,EDITPROC,ELSEIF," + // @J2A
+ "ENCODING,END-EXEC1," + // @J2A
+ "ERASE,EXCLUDING,EXIT,FENCED,FIELDPROC,FILE,FINAL,FREE,FUNCTION," + // @J2A
+ "GENERAL," + // @J2A
+ "GENERATED,GRAPHIC,HANDLER,HOLD,HOURS,IF,INCLUDING,INCREMENT," + // @J2A
+ "INDEX," + // @J2A
+ "INHERIT,INOUT,INTEGRITY,ISOBID,ITERATE,JAR,JAVA,LABEL,LC_CTYPE," + // @J2A
+ "LEAVE," + // @J2A
+ "LINKTYPE,LOCALE,LOCATOR,LOCATORS,LOCK,LOCKMAX,LOCKSIZE,LONG,LOOP," + // @J2A
+ "MAXVALUE,MICROSECOND,MICROSECONDS,MINUTES,MINVALUE,MODE,MODIFIES," + // @J2A
+ "MONTHS," + // @J2A
+ "NEW,NEW_TABLE,NOCACHE,NOCYCLE,NODENAME,NODENUMBER,NOMAXVALUE," + // @J2A
+ "NOMINVALUE," + // @J2A
+ "NOORDER,NULLS,NUMPARTS,OBID,OLD,OLD_TABLE,OPTIMIZATION,OPTIMIZE," + // @J2A
+ "OUT,OVERRIDING,PACKAGE,PARAMETER,PART,PARTITION,PATH,PIECESIZE," + // @J2A
+ "PLAN," + // @J2A
+ "PRIQTY,PROGRAM,PSID,QUERYNO,READS,RECOVERY,REFERENCING,RELEASE," + // @J2A
+ "RENAME,REPEAT,RESET,RESIGNAL,RESTART,RESULT,RESULT_SET_LOCATOR," + // @J2A
+ "RETURN," + // @J2A
+ "RETURNS,ROUTINE,ROW,RRN,RUN,SAVEPOINT,SCRATCHPAD,SECONDS,SECQTY," + // @J2A
+ "SECURITY,SENSITIVE,SIGNAL,SIMPLE,SOURCE,SPECIFIC,SQLID,STANDARD," + // @J2A
+ "START,STATIC,STAY,STOGROUP,STORES,STYLE,SUBPAGES,SYNONYM,SYSFUN," + // @J2A
+ "SYSIBM," + // @J2A
+ "SYSPROC,SYSTEM,TABLESPACE,TRIGGER,TYPE,UNDO,UNTIL,VALIDPROC," + // @J2A
+ "VARIABLE," + // @J2A
+ "VARIANT,VCAT,VOLUMES,WHILE,WLM,YEARS"; // @J2A
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates whether the SQLSTATEs returned by SQLException.getSQLState is X/Open SQL CLI or
+ SQL99.
+
+ @return Always sqlStateSQL99.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public int getSQLStateType ()
+ throws SQLException
+ {
+ return AS400JDBCDatabaseMetaData.sqlStateSQL99;
+ }
+
+
+
+ /**
+ Returns the list of supported string functions.
+
+ @return The list of supported string functions, separated by commas.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getStringFunctions ()
+ throws SQLException
+ {
+ // @J0A added try/catch because we are now sending the system VMR
+ return JDEscapeClause.getStringFunctions(connection_.getVRM()); // @J0M changed to send host version
+ }
+
+
+
+ //@G4A
+ /**
+ Returns a ResultSet containing descriptions of the table hierarchies
+ in a schema.
+
+ This method only applies to the attributes of a
+ structured type. Distinct types are stored in the datatypes
+ catalog, not the attributes catalog. Since DB2 for IBM i does not support
+ structured types at this time, an empty ResultSet will always be returned
+ for calls to this method.
+
+ @param catalog The catalog name.
+ @param schemaPattern The schema name pattern.
+ @param typeNamePattern The type name pattern.
+
+ @return The empty ResultSet
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public ResultSet getSuperTables (String catalog, String schemaPattern, String typeNamePattern)
+ throws SQLException
+ {
+ // We return an empty result set because this is not supported by our driver
+ Statement statement = connection_.createStatement();
+ return statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " +
+ "VARCHAR('2', 128) AS TYPE_SCHEM, " +
+ "VARCHAR('3', 128) AS TYPE_NAME, " +
+ "VARCHAR('4', 128) AS SUPERTYPE_NAME " +
+ "FROM QSYS2" + getCatalogSeparator() +
+ "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY ");
+ }
+
+
+
+ //@G4A
+ /**
+ Returns a ResultSet containing descriptions of user-defined type hierarchies
+ in a schema.
+
+ This method only applies to the attributes of a
+ structured type. Distinct types are stored in the datatypes
+ catalog, not the attributes catalog. Since DB2 for IBM i does not support
+ structured types at this time, an empty ResultSet will always be returned
+ for calls to this method.
+
+ @param catalog The catalog name.
+ @param schemaPattern The schema name pattern.
+ @param typeNamePattern The type name pattern.
+
+ @return The empty result set
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public ResultSet getSuperTypes (String catalog, String schemaPattern, String typeNamePattern)
+ throws SQLException
+ {
+ // We return an empty result set because this is not supported by our driver
+ Statement statement = connection_.createStatement();
+ return statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " +
+ "VARCHAR('2', 128) AS TYPE_SCHEM, " +
+ "VARCHAR('3', 128) AS TYPE_NAME, " +
+ "VARCHAR('4', 128) AS SUPERTYPE_CAT, " +
+ "VARCHAR('5', 128) AS SUPERTYPE_SCHEM, " +
+ "VARCHAR('6', 128) AS SUPERTYPE_NAME " +
+ "FROM QSYS2" + getCatalogSeparator() +
+ "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY ");
+ }
+
+
+
+ /**
+ Returns the list of supported system functions.
+
+ @return The list of supported system functions, separated by commas.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public String getSystemFunctions ()
+ throws SQLException
+ {
+ // @J0A added try/catch because we are now sending the system VMR
+ return JDEscapeClause.getSystemFunctions(connection_.getVRM()); // @J0M changed to send host version
+ }
+
+
+
+ /**
+ Returns the description of the access rights for each table
+ available in a catalog. Note that a table privilege applies
+ to one or more columns in a table.
+
+ @param catalog The catalog name. If null is specified, this parameter
+ is ignored. If empty string is specified,
+ an empty result set is returned.
+ @param schemaPattern The schema name pattern.
+ If the "metadata source" connection property is set to 0
+ and null is specified, no value is sent to the system and
+ the default of *USRLIBL is used.
+ If the "metadata source" connection property is set to 1
+ and null is specified, then information from all schemas
+ will be returned.
+
+ If empty string is specified, an empty
+ result set is returned.
+ @param tablePattern The table name. If null is specified,
+ no value is sent to the system and the system
+ default of *ALL is used. If empty string
+ is specified, an empty result set is returned.
+ @return The ResultSet containing the description of the
+ access rights for each table available in the
+ catalog.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getTablePrivileges (String catalog,
+ String schemaPattern,
+ String tablePattern)
+ throws SQLException
+ {
+ DBReplyRequestedDS reply = null;
+ connection_.checkOpen ();
+ // int vrm = connection_.getVRM(); //@trunc3
+
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL+ getCatalogSeparator () + "SQLTABLEPRIVILEGES(?,?,?,?)");
+
+ cs.setString(1, normalize(catalog));
+ cs.setString(2, normalize(schemaPattern));
+ cs.setString(3, normalize(tablePattern));
+ cs.setString(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
+ cs.execute();
+
+ ResultSet rs = cs.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cs.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+ //-----------------------------------------------------
+ // Set up the result set in the format required by JDBC
+ //--------------------------------------------------------
+
+ String[] fieldNames = {"TABLE_CAT",
+ "TABLE_SCHEM",
+ "TABLE_NAME",
+ "GRANTOR",
+ "GRANTEE",
+ "PRIVILEGE",
+ "IS_GRANTABLE",
+ };
+
+
+ SQLData[] sqlData = { new SQLVarchar (128, settings_), // catalog
+ new SQLVarchar (128, settings_), // library
+ new SQLVarchar (128, settings_), // table
+ new SQLVarchar (128, settings_), // grantor
+ new SQLVarchar (128, settings_), // grantee
+ new SQLVarchar (128, settings_), // privilege
+ new SQLVarchar (3, settings_), // is_grantable
+ };
+
+ int[] fieldNullables = {columnNullable, // catalog
+ columnNullable, // library
+ columnNoNulls, // table
+ columnNullable, // grantor
+ columnNoNulls, // grantee
+ columnNoNulls, // privilege
+ columnNullable, // is_grantable
+ };
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+
+ JDRowCache rowCache = null; // Creates a set of rows
+ // that are readable one at a time.
+ try
+ {
+ // Check for conditions that would result in an empty result set
+ // Must check for null first to avoid NullPointerException
+ if (!isCatalogValid(catalog) || // catalog is empty string
+
+ // schema is not null and is empty string
+ ((schemaPattern != null) && (schemaPattern.length()==0)) ||
+
+ // table is not null and is empty string
+ ((tablePattern != null) && (tablePattern.length()==0)))
+ { // Return empty result set
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+
+ else
+ { // parameter values are valid, build request & send
+ // Create a request
+ //@P0C
+ DBReturnObjectInformationRequestDS request = null;
+ try
+ {
+ request = DBDSPool.getDBReturnObjectInformationRequestDS (
+ DBReturnObjectInformationRequestDS.FUNCTIONID_FILE_INFO,
+ id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA +
+ DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT +
+ DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0);
+
+ // Set the library name and search pattern indicator
+ // If null, do not set parameter. The system default
+ // value of *USRLIBL is used.
+ if (schemaPattern!=null)
+ {
+ JDSearchPattern schema = new JDSearchPattern(schemaPattern);
+ request.setLibraryName(normalize(schema.getPatternString()), connection_.converter_); // @E4C
+ request.setLibraryNameSearchPatternIndicator(schema.getIndicator());
+ }
+
+
+
+ // Set the table name and search pattern indicator
+ // If null, do not set parameter. The system default
+ // value of *ALL is used.
+ if (tablePattern!=null)
+ {
+ JDSearchPattern table = new JDSearchPattern(tablePattern);
+ request.setFileName(normalize(table.getPatternString()),connection_.converter_); // @E4C
+ request.setFileNameSearchPatternIndicator(table.getIndicator());
+ }
+
+ request.setFileShortOrLongNameIndicator (0xF0); // Long table names
+
+
+ request.setFileReturnInfoBitmap (0xA1000000); // Return bitmap
+
+ // Order the results by table type, table schema, table name
+ request.setFileInfoOrderByIndicator (2);
+
+
+ //--------------------------------------------------------
+ // Send the request and cache all results from the system
+ //--------------------------------------------------------
+
+ reply = connection_.sendAndReceive(request);
+
+
+ // Check for errors - throw exception if errors were
+ // returned
+ int errorClass = reply.getErrorClass();
+ if (errorClass !=0)
+ {
+ int returnCode = reply.getReturnCode();
+ if (reply != null) { reply.returnToPool(); reply = null; }
+ throw JDError.throwSQLException (this, connection_, id_,
+ errorClass, returnCode);
+ }
+
+
+ // Get the data format and result data
+ DBDataFormat dataFormat = reply.getDataFormat();
+ DBData resultData = reply.getResultData();
+
+ // Put the data format into a row object
+ JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_);
+
+ // Put the result data into a row cache
+ JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache (row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+ // Create the mapped row format that is returned in the
+ // result set.
+ // This does not actual move the data, it just sets up
+ // the mapping.
+ JDFieldMap[] maps = new JDFieldMap[7];
+ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog ());
+ maps[1] = new JDSimpleFieldMap (1); // library
+ maps[2] = new JDSimpleFieldMap (2); // table
+ maps[3] = new JDHardcodedFieldMap ("", true, false); // grantor
+ maps[4] = new JDHardcodedFieldMap (getUserName ()); // grantee - return userid
+ maps[5] = new JDPrivilegeFieldMap (3); // privilege
+ maps[6] = new JDHardcodedFieldMap ("", true, false); // is_grantable
+
+ // Create the mapped row cache that is returned in the
+ // result set
+ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
+ rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
+
+ }
+ finally
+ {
+ if (request != null) { request.returnToPool(); request = null;}
+ // if (reply != null) { reply.returnToPool(); reply = null; }
+ }
+ } // End of else to build and send request
+ } // End of try block
+
+ catch (DBDataStreamException e)
+ {
+ // if (reply != null) { reply.returnToPool(); reply = null; }
+ JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
+ }
+
+ // Return the results
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(),
+ "TablePrivileges", connection_, reply); //@in2 //@G4C
+ }
+
+
+
+ /**
+ Returns the description of the tables available in a catalog.
+
+ @param catalog The catalog name. If null is specified, this parameter
+ is ignored. If empty string is specified,
+ an empty result set is returned.
+ @param schemaPattern The schema name pattern.
+ If the "metadata source" connection property is set to 0
+ and null is specified, no value is sent to the system and
+ the default of *USRLIBL is used.
+ If the "metadata source" connection property is set to 1
+ and null is specified, then information from all schemas
+ will be returned. If an empty string
+ is specified, an empty result set is returned.
+ @param tablePattern The table name pattern. If null is specified,
+ no value is sent to the system and the system
+ default of *ALL is used. If empty string
+ is specified, an empty result set is returned.
+ @param tableTypes The list of table types to include, or null to
+ include all table types. Valid types are:
+ TABLE, VIEW, SYSTEM TABLE, MATERIALIZED QUERY TABLE, and ALIAS.
+ @return The ResultSet containing the description of the
+ tables available in the catalog.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getTables (String catalog,
+ String schemaPattern,
+ String tablePattern,
+ String tableTypes[])
+ throws SQLException
+ {
+ DBReplyRequestedDS reply = null;
+
+ connection_.checkOpen ();// Verify that a connection
+ // is available for use. Exception
+ // is thrown if not available
+
+ // int vrm = connection_.getVRM(); //@trunc3
+
+
+ //@mdsp SYSIBM SP Call and Native logic
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ // Handle processing the array of table types.
+ //bite the bullet and follow Native JDBC logic
+ boolean rsEmpty = false;
+ String typeString = EMPTY_STRING;
+ if (!rsEmpty) {
+ int i;
+ int stringsInList = 0;
+
+ if (tableTypes != null) {
+ for (i = 0; i < tableTypes.length; i++) {
+ String check = tableTypes[i];
+
+ if ((check.equalsIgnoreCase(VIEW)) ||
+ (check.equalsIgnoreCase(TABLE)) ||
+ (check.equalsIgnoreCase(SYSTEM_TABLE)) ||
+ (check.equalsIgnoreCase(ALIAS)) ||
+ (check.equalsIgnoreCase(SYNONYM)) ||
+ (check.equalsIgnoreCase(MQT)))
+ {
+
+ if (check.equalsIgnoreCase(SYNONYM)) {
+ check = ALIAS;
+ }
+ stringsInList++;
+ if (stringsInList > 1)
+ typeString = typeString.concat(",");
+ typeString = typeString.concat(check);
+ }
+ }
+
+ // If there were no valid types, ensure an empty result set.
+ if (stringsInList == 0)
+ rsEmpty = true;
+ }
+ }
+
+ // If an empty result set is to be generated, produce the values to
+ // do so here.
+ if (rsEmpty) {
+ schemaPattern = FAKE_VALUE;
+ tablePattern = FAKE_VALUE;
+ typeString = typeString.concat(TABLE); //@scan1
+ }
+
+
+ CallableStatement cs = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator ()
+ + "SQLTABLES(?,?,?,?,?)");
+
+ cs.setString(1, normalize(catalog));
+ cs.setString(2, normalize(schemaPattern));
+ cs.setString(3, normalize(tablePattern));
+ cs.setString(4, normalize(typeString));
+ cs.setString(5,
+ "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
+ cs.execute();
+ ResultSet rs = cs.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cs.close(); //@mdrs2
+
+ return rs; //@mdrs
+
+ }
+
+
+ //-----------------------------------------------------
+ // Set up the result set in the format required by JDBC
+ //-----------------------------------------------------
+
+ boolean isJDBC3 = JDUtilities.JDBCLevel_ >= 30; //@F2A @j4a
+
+ String[] fieldNames = null; //@F2C
+ SQLData[] sqlData = null; //@F2C
+ int[] fieldNullables = null; //@F2C
+ if (!isJDBC3) //@F2A
+ {
+ fieldNames = new String[] { "TABLE_CAT",
+ "TABLE_SCHEM",
+ "TABLE_NAME",
+ "TABLE_TYPE",
+ "REMARKS"};
+
+ sqlData = new SQLData[] { new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (254, settings_)};
+
+
+ fieldNullables = new int[] {columnNullable, // Table catalog
+ columnNullable, // Table schema
+ columnNoNulls, // Table name
+ columnNoNulls, // Table type
+ columnNoNulls}; // Remarks
+ }
+ else
+ {
+ fieldNames = new String[] { "TABLE_CAT",
+ "TABLE_SCHEM",
+ "TABLE_NAME",
+ "TABLE_TYPE",
+ "REMARKS",
+ "TYPE_CAT", //@G4A
+ "TYPE_SCHEM", //@G4A
+ "TYPE_NAME", //@G4A
+ "SELF_REFERENCING_COL_NAME", //@G4A
+ "REF_GENERATION"}; //@G4A
+
+ sqlData = new SQLData[] { new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (128, settings_),
+ new SQLVarchar (254, settings_),
+ new SQLVarchar (128, settings_), //@G4A
+ new SQLVarchar (128, settings_), //@G4A
+ new SQLVarchar (128, settings_), //@G4A
+ new SQLVarchar (128, settings_), //@G4A
+ new SQLVarchar (128, settings_)}; //@G4A
+
+
+ fieldNullables = new int[] {columnNullable, // Table catalog
+ columnNullable, // Table schema
+ columnNoNulls, // Table name
+ columnNoNulls, // Table type
+ columnNoNulls, // Remarks
+ columnNullable, // Types catalog //@G4A
+ columnNullable, // Types schema //@G4A
+ columnNullable, // Type name //@G4A
+ columnNullable, // Self referencing column name //@G4A
+ columnNullable}; // Reference generation //@G4A
+ }
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+
+ JDRowCache rowCache = null; // Creates a set of rows that
+ // are readable one at a time
+ try
+ {
+ // Check for conditions that would result in an empty result set
+ // Must check for null first to avoid NullPointerException
+ if (!isCatalogValid(catalog) || // catalog is empty string
+
+ // schema is not null and is empty string
+ ((schemaPattern != null) && (schemaPattern.length()==0)) ||
+
+ // table is not null and is empty string
+ ((tablePattern != null) && (tablePattern.length()==0)))
+ { // Return empty result set
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+
+ else
+ { // schema, table, and catalog are valid, create and send request
+
+ //-------------------------------------------------------
+ // Set the file attribute parm of the Retrieve File
+ // Information (ROI) function based on the types array
+ // provided. ROI uses the following values:
+ // '0001'x = all files
+ // '0002'x = physical files and alias files
+ // '0003'x = logical files and alias files
+ // '0004'x = tables and alias files
+ // '0005'x = views and alias files
+ // '0006'x = system tables
+ // '0007'x = tables and views and alias files
+ // '0008'x = tables and system tables and alias files
+ // '0009'x = views and system tables and alias files
+ // '000A'x = alias files //@K1A
+ // '000B'x = tables and materialized query tables //@K1A
+ // '000C'x = views and materialized query tables //@K1A
+ // '000D'x = system tables and materialized query tables //@K1A
+ // '000E'x = tables, views, and materialized query tables //@K1A
+ // '000F'x = tables, system tables, and materialized query tables //@K1A
+ // '0010'x = views, system tables, and materizlized query tables //@K1A
+ // '0011'x = materialized query tables //@K1A
+ //
+ // Options '000B'x - '0011'x are for V5R3 or higher systems
+ //
+ // If null is specified, file attributes is set to 1.
+ //
+ // If none of the above values are specified, file
+ // attribute is set to -1 and an empty result set will
+ // be created. No request is sent to the system.
+ //--------------------------------------------------------
+ int fileAttribute;
+ boolean needToRemoveAliases = true;
+ if (tableTypes != null)
+ {
+ boolean typeTable = false; // false = don't include table type
+ boolean typeView = false;
+ boolean typeSystemTable = false;
+ boolean typeMQTable = false;
+ boolean typeAlias = false;
+
+ // Walk thru table types to determine which ones we need to include
+ for (int i = 0; i < tableTypes.length; ++i)
+ {
+ if (tableTypes[i].equalsIgnoreCase ("TABLE"))
+ typeTable = true; // Include tables
+ else if (tableTypes[i].equalsIgnoreCase ("VIEW"))
+ typeView = true; // Include views
+ else if (tableTypes[i].equalsIgnoreCase ("SYSTEM TABLE"))
+ typeSystemTable = true; // Include system tables
+ else if (tableTypes[i].equalsIgnoreCase ("MATERIALIZED QUERY TABLE") && connection_.getVRM() >= JDUtilities.vrm530) //@K1A
+ typeMQTable = true; //@K1A
+ else if(tableTypes[i].equalsIgnoreCase("ALIAS"))
+ typeAlias = true;
+ } // end of for loop
+
+ if(typeAlias)
+ needToRemoveAliases = false;
+
+ if (typeTable)
+ {
+ if (typeView)
+ {
+ if (typeSystemTable)
+ fileAttribute = 1; // All
+ else if(typeMQTable) //@K1A
+ {
+ fileAttribute = 14; //tables, views, and MQT's //@K1A
+ needToRemoveAliases = false;
+ }
+ else
+ fileAttribute = 7; // Tables and views
+ }
+ else if(typeSystemTable) //@K1A Not Views
+ { //@K1A
+ if(typeMQTable) //@K1A
+ {
+ fileAttribute = 15; //@K1A
+ needToRemoveAliases = false; // no aliases are returned
+ }
+ else //@K1A
+ fileAttribute = 8; // Tables and system tables
+ } //@K1A
+ else if(typeMQTable) //@K1A Not Views and not system tables
+ { //@K1A
+ fileAttribute = 11; //@K1A
+ needToRemoveAliases = false; // no aliases are returned
+ } //@K1A
+ else
+ fileAttribute = 4; // Tables
+ } // end of if typeTable
+ else if(typeMQTable) //@K1A
+ { //@K1A
+ if(typeView) //@K1A
+ { //@K1A
+ if(typeSystemTable) //@K1A
+ fileAttribute = 16; //views, system tables, and MQT's //@K1A
+ else //@K1A
+ fileAttribute = 12; //views and MQT's //@K1A
+ } //@K1A
+ else if(typeSystemTable) //@K1A
+ fileAttribute = 13; //system tables and MQT's //@K1A
+ else //@K1A
+ fileAttribute = 17; //MQT's //@K1A
+ needToRemoveAliases = false; //no aliases are returned
+ } //@K1A
+ else
+ { // Not tables
+ if (typeView)
+ {
+ if (typeSystemTable)
+ fileAttribute = 9; // Views and system tables
+ else
+ fileAttribute = 5; // Views
+ }
+ else
+ {
+ if (typeSystemTable)
+ {
+ fileAttribute = 6; // System tables
+ needToRemoveAliases = false; // no aliases are returned
+ }
+ else if(typeAlias && connection_.getVRM() >= JDUtilities.vrm430) // Aliases are only supported on V4R3 and higher
+ fileAttribute = 10;
+ else
+ fileAttribute = -1; // Unknown type
+ // Will return empty results
+ }
+ } // End of not tables else
+ } // End of if tables != nulls
+ else
+ {
+ // Table types was set to null which implies all
+ // types are to be returned
+ fileAttribute = 1; // All
+ }
+
+
+ //------------------------------------------------
+ // Create the request to Retrieve File Information
+ //------------------------------------------------
+ if (fileAttribute != -1)
+ { // If -1, return empty set
+ // Create a request
+ //@P0C
+ DBReturnObjectInformationRequestDS request = null;
+ try
+ {
+ request = DBDSPool.getDBReturnObjectInformationRequestDS (
+ DBReturnObjectInformationRequestDS.FUNCTIONID_FILE_INFO, id_,
+ DBBaseRequestDS.ORS_BITMAP_RETURN_DATA
+ + DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT
+ + DBBaseRequestDS.ORS_BITMAP_RESULT_DATA,0);
+
+
+ //--------------------------------------------------
+ // Set the parameters for the request
+ //--------------------------------------------------
+
+
+ // Set the Library Name and Library Name Search Pattern parameters
+ // If null, do not set parameter. The system default value of
+ // *USRLIBL is used.
+ if (schemaPattern != null)
+ { // use default SQL schema or qgpl
+ JDSearchPattern schema = new JDSearchPattern(schemaPattern);
+ request.setLibraryName (normalize(schema.getPatternString()), connection_.converter_); // @E4C
+ request.setLibraryNameSearchPatternIndicator(schema.getIndicator());
+ }
+
+
+
+ // Set the Table Name and Table Name Search Pattern parameters
+ // If null, do not set parameter. The system default value of
+ // *ALL is used.
+ if (tablePattern!=null)
+ {
+ JDSearchPattern table = new JDSearchPattern(tablePattern);
+ request.setFileName (normalize(table.getPatternString()), connection_.converter_); // @E4C
+ request.setFileNameSearchPatternIndicator(table.getIndicator());
+ }
+
+
+
+ // Set other parameters
+ request.setFileShortOrLongNameIndicator (0xF0); // Long table names.
+ request.setFileAttribute (fileAttribute);
+
+ // Set the information to return. Always return the
+ // library name, file name, and file attribute (ODBC
+ // type). Also return either the remarks or the file
+ // text depending on what the "remarks" attribute
+ // is set to.
+
+ // Get the current value for the "remarks" property
+ // and check to see if it is sql or system
+ // connection_.getProperties() returns the JDProperties
+ // object
+
+
+ if (connection_.getProperties().equals
+ (JDProperties.REMARKS, JDProperties.REMARKS_SQL))
+ {
+ request.setFileReturnInfoBitmap (0xF0000000); // return remarks
+ }
+ else
+ {
+ request.setFileReturnInfoBitmap (0xB4000000); // return text
+ }
+
+ // Order the results by table type, table schema, table name
+ // This is the same as ordering by tables on the system
+ request.setFileInfoOrderByIndicator (2);
+
+
+ //-------------------------------------------------------
+ // Send the request and cache all results from the system
+ //-------------------------------------------------------
+
+ reply = connection_.sendAndReceive (request);
+
+ // Check for errors - throw exception if errors
+ // were returned
+ int errorClass = reply.getErrorClass();
+ if (errorClass != 0)
+ {
+ int returnCode = reply.getReturnCode();
+ if (reply != null) { reply.returnToPool(); reply = null; }
+ throw JDError.throwSQLException (this, connection_, id_,
+ errorClass, returnCode);
+ }
+
+
+ // Get the data format and result data
+ // The result data is parsed via JDServerRow getData
+ DBDataFormat dataFormat = reply.getDataFormat ();
+ DBData resultData = reply.getResultData ();
+ if (resultData != null)
+ {
+ // If the user didn't request aliases
+ if(needToRemoveAliases)
+ parseResultData(resultData, dataFormat);
+
+ // Put the data format into a row format. Handles data types
+ JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_);
+
+ // Put the result data into a row cache
+ // ServerRowCache needs rowFormat to get offset and other info
+ // Only need this with this type of row cache (not with simple)
+ JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE));
+
+ // This is not actually moving data, it just sets up the mapping
+ JDFieldMap[] maps = null; //@F2C
+ if (!isJDBC3) //@F2A
+ maps = new JDFieldMap[5];
+ else
+ maps = new JDFieldMap[10];
+
+ if (connection_.getProperties().equals
+ (JDProperties.REMARKS, JDProperties.REMARKS_SQL))
+ {
+ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog());
+ maps[1] = new JDSimpleFieldMap (1); // schema // @A3C @E4C
+ maps[2] = new JDSimpleFieldMap (3); // table
+ maps[3] = new JDTableTypeFieldMap (4); // table type
+ maps[4] = new JDSimpleFieldMap (2); // remarks
+ //@G4A The below fields will all return null. We have distinct types
+ //@G4A instead of abstract types here, so a request returns no
+ //@G4A type information.
+ if (isJDBC3)
+ {
+ maps[5] = new JDHardcodedFieldMap ("", true, false); // types catalog //@G4A
+ maps[6] = new JDHardcodedFieldMap ("", true, false); // types schema //@G4A
+ maps[7] = new JDHardcodedFieldMap ("", true, false); // type name //@G4A
+ maps[8] = new JDHardcodedFieldMap ("", true, false); // self referencing col name //@G4A
+ maps[9] = new JDHardcodedFieldMap ("", true, false); // ref generation //@G4A
+ }
+ }
+
+ else
+ { // Get file text instead of remarks
+ maps[0] = new JDHardcodedFieldMap (connection_.getCatalog());
+ maps[1] = new JDSimpleFieldMap (1); // schema // @A3C @E4C
+ maps[2] = new JDSimpleFieldMap (2); // table
+ maps[3] = new JDTableTypeFieldMap (3); // table type
+ maps[4] = new JDSimpleFieldMap (4); // File text
+ //@G4A The below fields will all return null. We have distinct types
+ //@G4A instead of abstract types here, so a request returns no
+ //@G4A type information.
+ if (isJDBC3)
+ {
+ maps[5] = new JDHardcodedFieldMap ("", true, false); // types catalog //@G4A
+ maps[6] = new JDHardcodedFieldMap ("", true, false); // types schema //@G4A
+ maps[7] = new JDHardcodedFieldMap ("", true, false); // type name //@G4A
+ maps[8] = new JDHardcodedFieldMap ("", true, false); // self referencing col name //@G4A
+ maps[9] = new JDHardcodedFieldMap ("", true, false); // ref generation //@G4A
+ }
+ }
+
+ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
+ rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
+
+ }
+ else
+ rowCache = new JDSimpleRowCache(formatRow);
+
+ }
+ finally
+ {
+ if (request != null) { request.returnToPool(); request = null; }
+ // if (reply != null) { reply.returnToPool(); reply = null; }
+ }
+ } // End of if file attribute != -1
+ else
+ { // result set should be empty.
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+ } // End of else to create and send request
+
+ } // End of try block
+
+ catch (DBDataStreamException e)
+ {
+ // if (reply != null) { reply.returnToPool(); reply = null; }
+ JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
+ }
+
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(),
+ "Tables", connection_, reply); //@in2
+ }
+
+
+// Parses the result data from the system to determine if any aliases were returned.
+ void parseResultData(DBData resultData, DBDataFormat dataFormat) {
+ try{
+ byte[] rawBytes = resultData.getRawBytes();
+ int rowCount = resultData.getRowCount();
+ int columnOffset = dataFormat.getFieldLength(0); // schema
+ columnOffset += dataFormat.getFieldLength(1); // table
+ int tableTypeLength = dataFormat.getFieldLength(2); // table type
+ SQLChar tableType = new SQLChar(tableTypeLength, settings_); // create an sql char ojbect to get the table type
+ int aliasCount = 0;
+ ConvTable ccsidConverter = connection_.getConverter(dataFormat.getFieldCCSID(2));
+ for(int i=0; i This chart describes the combinations of result set concurrency
+ and type that this driver supports:
+
+ *
+ * The
+ * @return A
+ * @exception SQLException if a database access error occurs
+ *
+ */
+ public ResultSet getClientInfoProperties() throws SQLException
+ {
+ // Set up the result set.
+ int vrm = connection_.getVRM(); //@trunc3
+ String[] fieldNames = { "NAME", "MAX_LEN", "DEFAULT_VALUE", "DESCRIPTION" };
+ SQLData[] sqlData = { new SQLVarchar(32, settings_), new SQLInteger(vrm,settings_), new SQLVarchar(32, settings_), new SQLVarchar(1024, settings_) }; //trunc3
+ int[] fieldNullables = {columnNoNulls, columnNoNulls, columnNoNulls, columnNoNulls}; // table types can not be null
+
+ Object[][] data = { { "ApplicationName", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_APPLICATIONNAME") },
+ { "ClientUser", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTUSER")},
+ { "ClientHostname", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTHOSTNAME")},
+ { "ClientAccounting", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTACCOUNTING")},
+ { "ClientProgramID", new Integer(255), "", AS400JDBCDriver.getResource ("CLIENT_INFO_DESC_CLIENTPROGRAMID")}}; //@pdc programID
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+ JDSimpleRowCache rowCache = new JDSimpleRowCache(formatRow, data);
+
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(),
+ "Client Info", connection_, null); //@in2
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Indicates whether or not this data source supports the SQL
+ * The returned int values have the following relationship:
+ * The schema column is:
+ *
+ * Only system and user function descriptions matching the schema and
+ * function name criteria are returned. They are ordered by
+ * Each function description has the the following columns:
+ *
+ * A user may not have permissions to execute any of the functions that are
+ * returned by Only descriptions matching the schema, function and
+ * parameter name criteria are returned. They are ordered by
+ * Each row in the The PRECISION column represents the specified column size for the given
+ * parameter or column.
+ * For numeric data, this is the maximum precision. For character data, this is the length in characters.
+ * For datetime datatypes, this is the length in characters of the String representation (assuming the
+ * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
+ * this is the length in bytes. Null is returned for data types where the
+ * column size is not applicable.
+ * @param catalog a catalog name; must match the catalog name as it
+ * is stored in the database; "" retrieves those without a catalog;
+ * Only column descriptions matching the catalog, schema, table and column name criteria are returned.
+ * They are ordered by TABLE_CAT,TABLE_SCHEM, TABLE_NAME and COLUMN_NAME.
+ * Each column description has the following columns:
+ * The COLUMN_SIZE column specifies the column size for the given column. For numeric data, this is the
+ * maximum precision. For character data, this is the length in characters. For datetime datatypes,
+ * this is the length in characters of the String representation (assuming the maximum allowed precision of the
+ * fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
+ * this is the length in bytes. Null is returned for data types where the column size is not applicable.
+ *
+ * @param catalog - a catalog name; must match the catalog name as it is stored in the database;
+ * "" retrieves those without a catalog; null means that the catalog name should not be used to narrow the search
+ * @param schemaPattern - a schema name pattern; must match the schema name as it is stored in the database;
+ * "" retrieves those without a schema; null means that the schema name should not be used to narrow the search
+ * @param tableNamePattern - a table name pattern; must match the table name as it is stored in the database
+ * @param columnNamePattern - a column name pattern; must match the column name as it is stored in the database
+ * @return ResultSet - each row is a column description
+ * @exception SQLException - if a database access error occurs
+ * @see java.sql.PseudoColumnUsage
+ */
+
+ public ResultSet getPseudoColumns(String catalog, String schemaPattern,
+ String tableNamePattern, String columnNamePattern)
+ throws SQLException {
+
+ connection_.checkOpen();
+
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLPSEUDOCOLUMNS ( ?, ?, ?, ?, ?)");
+
+ cstmt.setString(1, normalize(catalog));
+ cstmt.setString(2, normalize(schemaPattern));
+ cstmt.setString(3, normalize(tableNamePattern));
+ cstmt.setString(4, normalize(columnNamePattern));
+/* ifdef JDBC40 */
+ cstmt.setObject(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp //@ver
+/* endif */
+/* ifndef JDBC40
+ cstmt.setObject(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp
+ endif */
+ cstmt.execute();//@mdrs
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCDriver.java b/jdbc40/com/ibm/as400/access/AS400JDBCDriver.java
new file mode 100644
index 000000000..5243a8d95
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCDriver.java
@@ -0,0 +1,1469 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCDriver.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.PropertyVetoException; // @B9A
+import java.net.InetAddress; // @C2A
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+/* endif */
+import java.util.Properties;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+
+/**
+A JDBC 3.0/4.0 driver that accesses DB2 for IBM i databases.
+
+ To use this driver, the application or caller must register
+the driver with the JDBC DriverManager. This class also registers
+itself automatically when it is loaded.
+
+ After registering the driver, applications make connection
+requests to the DriverManager, which dispatches them to the
+appropriate driver. This driver accepts connection requests
+for databases specified by the URLs that match the following syntax:
+
+ The driver uses the specified system name to connect
+to a corresponding IBM i system.
+If an IPV6 address is used as the system name, it must be enclosed within braces,
+i.e. [fd13:ac12:18:17::16].
+If a system name is not specified, then the user will be prompted.
+
+ The default SQL schema is optional and the driver uses it to resolve
+unqualified names in SQL statements. If no default SQL schema is set, then
+the driver resolves unqualified names based on the naming convention
+for the connection. If SQL naming is being used, and no default SQL schema
+is set, then the driver resolves unqualified names using the schema with
+the same name as the user. If system naming is being used, and no
+default SQL schema is set, then the driver resolves unqualified names using
+the server job's library list. See
+JDBC properties
+for more details on how to set the naming convention
+and library list.
+
+ Several properties can optionally be set within the URL. They are
+separated by semicolons and are in the form:
+ The following example URL specifies a connection to the
+database on system mysystem.helloworld.com with
+mylibrary as the default SQL schema. The connection will
+use the system naming convention and return full error messages:
+ Note: Since this method is not defined in the JDBC Driver interface,
+ you typically need to create a Driver object in order
+ to call this method:
+ Note: Since this method is not defined in the JDBC Driver interface,
+ you typically need to create a Driver object in order
+ to call this method:
+ Note: Since this method is not defined in the JDBC Driver interface,
+ you typically need to create a Driver object in order
+ to call this method:
+ Note: Since this method is not defined in the JDBC Driver interface,
+ you typically need to create a Driver object in order
+ to call this method:
+ The AS400JDBCInputStream class provides access to binary data
+using an input stream. The data is valid only within the current
+transaction.
+**/
+//
+// Implementation notes:
+//
+// 1. This implementation deals specifically with binary data
+// that is retrieved upon request with the locator handle.
+// The case where the binary data comes in full with the result
+// set can be stored directly in a ByteArrayInputStream.
+//
+// 2. We do not worry about buffering or caching, since the caller
+// can just wrap this in a BufferedInputStream if they want that.
+//
+class AS400JDBCInputStream extends InputStream
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+ private boolean closed_;
+ private JDLobLocator locator_;
+ private long offset_;
+ private long length_; //@pda jdbc40
+
+ private long mark_ = 0;
+
+/**
+Constructs an AS400JDBCInputStream object. The data for the
+binary stream will be retrieved as requested, directly from the
+system, using the locator handle.
+
+@param locator The locator.
+**/
+ AS400JDBCInputStream(JDLobLocator locator)
+ {
+ locator_ = locator;
+ offset_ = 0;
+ closed_ = false;
+ try //@pda jdbc40 set length (for sub-streams)
+ {
+ length_ = locator.getLength();
+ }catch(SQLException e)
+ {
+ length_ = 0;
+ closed_ = true;
+ }
+
+ }
+
+ //@pda jdbc40 new constructor
+ /**
+ Constructs an AS400JDBCInputStream object. The data for the
+ binary stream will be retrieved as requested, directly from the
+ system, using the locator handle.
+
+ @param locator The locator.
+ @param pos The starting position.
+ @param length The length of the stream.
+ **/
+ AS400JDBCInputStream(JDLobLocator locator, long pos, long length)
+ {
+ locator_ = locator;
+ offset_ = pos;
+ length_ = length;
+ closed_ = false;
+ long actualLen;
+ try
+ {
+ actualLen = locator.getLength();
+
+ }catch(SQLException e)
+ {
+ actualLen = 0;
+ closed_ = true;
+ }
+ if(length_ > actualLen)
+ length_ = actualLen;
+ }
+
+/**
+Returns the number of bytes that can be read without blocking.
+
+@return The number of bytes that can be read without blocking.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized int available() throws IOException
+ {
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ long returnValue = 0;
+ // try //@PDd jdbc40
+ // { //@PDd jdbc40
+ returnValue = length_ - offset_; //@PDC jdbc40
+
+ if (returnValue < 0) returnValue = 0;
+ // } //@PDd jdbc40
+ // catch (SQLException e) //@PDd jdbc40
+ // { //@PDd jdbc40
+ // if (JDTrace.isTraceOn()) //@PDd jdbc40
+ // { //@PDd jdbc40
+ // JDTrace.logInformation(this, "Error in available"); //@PDd jdbc40
+ // e.printStackTrace(DriverManager.getLogStream()); //@PDd jdbc40
+ // closed_ = true; //@PDd jdbc40
+ // } //@PDd jdbc40
+ // throw new IOException(e.getMessage()); //@PDd jdbc40
+ // } //@PDd jdbc40
+
+ if (returnValue > 0x7FFFFFFF) returnValue = 0x7FFFFFFF;
+
+ return(int)returnValue;
+ }
+
+
+
+/**
+Closes the stream and releases any associated system resources.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized void close() throws IOException
+ {
+ closed_ = true;
+ }
+
+
+
+/**
+Marks the current position in the stream.
+
+@param readLimit The read limit.
+@see #reset()
+**/
+ public synchronized void mark(int readLimit)
+ {
+ mark_ = offset_;
+ }
+
+
+
+/**
+Indicates if mark() and reset() are supported.
+
+@return true
+**/
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+
+
+/**
+Reads the next byte of data. This method blocks until data is
+available, the end of the stream is detected, or an exception
+is thrown.
+
+@return The next byte of data as an int in the range 0 to 255,
+ or -1 if no more data is available.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized int read() throws IOException
+ {
+ int returnValue = -1;
+
+ byte[] data = new byte[1]; // Yes, we allocate each time, but the user shouldn't be calling this method if they want performance to be good.
+ if (read(data, 0, 1) > 0) returnValue = data[0] & 0x00FF;
+
+ return returnValue;
+ }
+
+
+
+/**
+Reads bytes of data. This method blocks until
+data is available, the end of the stream is detected, or an
+exception is thrown.
+
+@param data The byte array to fill with data. This method
+ will read as much data as possible to fill
+ the array.
+@return The number of bytes of data read,
+ or -1 if no more data is available.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized int read(byte[] data) throws IOException
+ {
+ return read(data, 0, data.length);
+ }
+
+
+
+/**
+Reads bytes of data. This method blocks until
+data is available, the end of the stream is detected, or an
+exception is thrown.
+
+@param data The byte array to fill with data. This method
+ will read as much data as possible to fill
+ the array. All data may not be available to
+ read from the stream at once, only when this
+ method returns -1 can you be sure all of the
+ data was read.
+@param start The start position in the array.
+@param length The maximum number of bytes to read.
+@return The number of bytes of data read,
+ or -1 if no more data is available.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized int read(byte[] data, int start, int length) throws IOException
+ {
+ if (data == null) throw new NullPointerException("data");
+
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ if ((start < 0) || (start > data.length))
+ {
+ throw new ExtendedIllegalArgumentException("start", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ if ((length < 0) || (start + length > data.length))//@pdc locator_.retrieveData(,len) does not fail if len is greater that available length
+ {
+ throw new ExtendedIllegalArgumentException("length", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+
+ // Added this to prevent trying to read past the end of the stream.
+ if (length == 0)
+ {
+ return 0;
+ }
+
+ try
+ {
+ if (offset_ >= length_) //@PDC jdbc40
+ {
+ //@CRS - Is this really the end? Or is the end getMaxLength()?
+ return -1;
+ }
+
+ //@CRS: Can lengthRead ever be greater than length?
+ if (locator_.isGraphic()) length = length / 2;
+ DBLobData lobData = locator_.retrieveData(offset_, length);
+ int lengthRead = lobData.getLength();
+ if (lengthRead == 0)
+ {
+ closed_ = true;
+ return -1;
+ }
+ else
+ {
+ System.arraycopy(lobData.getRawBytes(), lobData.getOffset(), data, start, lengthRead);
+ offset_ += locator_.isGraphic() ? lengthRead / 2: lengthRead;
+ return lengthRead;
+ }
+ }
+ catch (SQLException e)
+ {
+ if (JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation(this, "Error in read" + e.getMessage()); //@pdc
+ //@pdd e.printStackTrace(DriverManager.getLogStream());
+ closed_ = true;
+ }
+ IOException throwException = new IOException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+
+/**
+Repositions to the marked position.
+If mark() has not been called, repositions to the beginning of the stream.
+
+@exception IOException If an input/output error occurs.
+@see #mark(int)
+**/
+ public synchronized void reset() throws IOException
+ {
+ offset_ = mark_;
+ }
+
+
+/**
+Skips over and discards data.
+
+@param length The maximum number of bytes to skip. If negative,
+ no bytes are skipped.
+@return The number of bytes skipped.
+
+@exception IOException If an input/output error occurs.
+**/
+ public synchronized long skip(long length) throws IOException
+ {
+ if (closed_)
+ {
+ throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+ }
+ if (length < 0)
+ {
+ throw new ExtendedIllegalArgumentException("length", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ if (length == 0) return 0;
+ //try //@PDD jdbc40
+ //{ //@PDD jdbc40
+ long newOffset = length + offset_;
+ long len = length_; //@PDC jdbc40
+
+ if (newOffset > len)
+ {
+ length = len - offset_;
+ offset_ = len;
+ }
+ else
+ {
+ offset_ = offset_ + length;
+ }
+ return length;
+ //} //@PDD jdbc40
+ //catch (SQLException e) //@PDD jdbc40
+ //{ //@PDD jdbc40
+ // if (JDTrace.isTraceOn()) //@PDD jdbc40
+ // { //@PDD jdbc40
+ // JDTrace.logInformation(this, "Error in skip"); //@PDD jdbc40
+ // e.printStackTrace(DriverManager.getLogStream()); //@PDD jdbc40
+ // } //@PDD jdbc40
+ // closed_ = true; //@PDD jdbc40
+ // throw new IOException(e.getMessage()); //@PDD jdbc40
+ //} //@PDD jdbc40
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCManagedDataSource.java b/jdbc40/com/ibm/as400/access/AS400JDBCManagedDataSource.java
new file mode 100644
index 000000000..186235bea
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCManagedDataSource.java
@@ -0,0 +1,4713 @@
+// TBD - Cross-link with corresponding non-managed class.
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCManagedDataSource.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) 2005-2010 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+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;
+/* endif */
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Random;
+/* ifdef JDBC40 */
+import java.util.logging.Logger;
+/* endif */
+
+import javax.sql.DataSource;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+
+// Note that there is no inheritance/extension relationship between DataSource and ConnectionPoolDataSource. Applications code to DataSource, whereas ConnectionPoolDataSource is used internally by application servers, etc.
+
+// Note: We currently have no requirement to provide a managed pooling implementation of javax.sql.XADataSource.
+
+/**
+ This implementation of javax.sql.DataSource can be used to produce Connection objects that will automatically participate in connection pooling, and are managed by the Toolbox's built-in connection pooling manager.
+
+
+ A DataSource is a factory for connections to the physical data source that this DataSource object represents.
+ An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection.
+ An object that implements the DataSource interface will typically be registered with a naming service based on the
+ Java Naming and Directory (JNDI) API.
+
+ A DataSource object has properties that can be modified when necessary. For example, if the data source is moved to a
+ different system, the property for the system can be changed. The benefit is that because the data source's properties
+ can be changed, any code accessing that data source does not need to be changed.
+
+ A driver that is accessed via a DataSource object does not register itself with the DriverManager. Rather, a DataSource o
+ bject is retrieved though a lookup operation and then used to create a Connection object. With a basic implementation,
+ the connection obtained through a DataSource object is identical to a connection obtained through the DriverManager facility.
+
+ Caution: To avoid the pitfalls of "double-managed" pools, do not use this class in conjunction with a separate
+ connection pool manager, such as that available in WebSphere. When a separate pool manager is provided,
+ use {@link AS400JDBCDataSource AS400JDBCDataSource} instead.
+
+ @see AS400JDBCManagedConnectionPoolDataSource
+ @see AS400JDBCDataSource
+ @see AS400JDBCConnectionPoolDataSource
+ @see AS400JDBCXADataSource
+ **/
+public class AS400JDBCManagedDataSource
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+
+implements DataSource, Referenceable, Serializable, Cloneable //@PDC 550
+{
+ private static final long serialVersionUID = 1L;
+static final String copyright = "Copyright (C) 2005-2010 International Business Machines Corporation and others.";
+ private static final boolean DEBUG = false;
+
+
+ /**
+ Implementation notes:
+ The properties listed in com.ibm.as400.access.JDProperties should also be included here.
+ **/
+
+ // Note:
+ // There are three kinds of data sources:
+ // 1. Basic DataSource (javax.sql.DataSource). Provides a getConnection() method that returns an instance of java.sql.Connection.
+ // 2. Data source class implemented to provide connection pooling (javax.sql.ConnectionPoolDataSource). Provides a getPooledConnection() method that returns an instance of javax.sql.PooledConnection.
+ // 3. Data Source class implemented to provide distributed transactions (javax.sql.XADataSource). Provides a getXAConnection() method that returns an instance of javax.sql.XAConnection.
+
+ // Constants
+ 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 = "user"; // same as JDProperties.USER_
+ private static final String KEY_RING_NAME = "key ring name"; // same as JDProperties.KEY_RING_NAME_
+ private static final String PASSWORD = "pw"; // same as JDProperties.PASSWORD_
+ private static final String KEY_RING_PASSWORD = "key ring password"; // same as JDProperties.KEY_RING_PASSWORD_
+ private static final String SECURE = "secure"; // same as JDProperties.SECURE_
+ private static final String SAVE_PASSWORD = "savepw";
+ private static final String PLAIN_TEXT_PASSWORD = "pwd";
+ 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).
+
+ // socket options to store away in JNDI
+ private static final String SOCKET_KEEP_ALIVE = "soKeepAlive";
+ // JDProperties: "keep alive"
+ private static final String SOCKET_RECEIVE_BUFFER_SIZE = "soReceiveBufferSize";
+ // JDProperties: "receive buffer size"
+ private static final String SOCKET_SEND_BUFFER_SIZE = "soSendBufferSize";
+ // JDProperties: "send buffer size"
+ private static final String SOCKET_LINGER = "soLinger";
+ private static final String SOCKET_TIMEOUT = "soTimeout";
+ private static final String SOCKET_TCP_NO_DELAY = "soTCPNoDelay";
+
+ // Standard data source properties. (See JDBC Tutorial p. 567, table 16.1)
+
+ transient private AS400 as400_; // Object used to store and encrypt the password.
+ private String dataSourceName_; // Data source name.
+ private String description_; // Data source description.
+ // Note: A "networkProtocol" property is not provided. The Toolbox JDBC driver uses only 1 protocol, specified in the JDProperties.
+ // Note: For security, password value is stored in serialPWBytes_, and no getPassword() method is provided.
+ private char[] serialPWBytes_;
+ private int pwHashcode_; // hashed password
+ // Note: A "portNumber" property is not provided. It is specified in the JDProperties.
+ // Note: A "roleName" property is not provided.
+ private String serialServerName_; // system name used in serialization.
+ private String serialUserName_; // User name used in serialization.
+
+ // Additional properties.
+
+ private String serialKeyRingName_; // Key ring name used in serialization.
+ private boolean isSecure_;
+ private char[] serialKeyRingPWBytes_;
+ private boolean savePasswordWhenSerialized_; // By default, don't save password!!!!
+ private JDProperties properties_ = new JDProperties(); // system connection properties.
+ private SocketProperties sockProps_ = new SocketProperties(); // socket properties
+
+ // Internal utility fields.
+
+ transient private PrintWriter writer_; // The EventLog print writer.
+ transient EventLog log_;
+
+ transient private AS400JDBCManagedConnectionPoolDataSource cpds_;
+
+ // Handles loading the appropriate resource bundle
+ // private static ResourceBundleLoader loader_;
+
+ private boolean dataSourceNameSpecified_;
+ transient private JDConnectionPoolManager poolManager_;
+ transient private boolean poolManagerInitialized_;
+
+ transient private JDConnectionPoolKey defaultConnectionPoolKey_;
+ transient private boolean connectionKeyNeedsUpdate_ = true;
+
+ transient private boolean inUse_;
+
+ /**
+ * The maximum storage space that can be used to execute a query.
+ **/
+ public static final int MAX_STORAGE_LIMIT = AS400JDBCDataSource.MAX_STORAGE_LIMIT; // 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 = AS400JDBCDataSource.TRACE_CLIENT;
+
+ /**
+ 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 = AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR;
+
+ /**
+ 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 = AS400JDBCDataSource.SERVER_TRACE_DEBUG_SERVER_JOB;
+
+ /**
+ 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 = AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG;
+
+ /**
+ 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 = AS400JDBCDataSource.SERVER_TRACE_TRACE_SERVER_JOB;
+
+ /**
+ 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 = AS400JDBCDataSource.SERVER_TRACE_SAVE_SQL_INFORMATION;
+
+
+ /**
+ Constructs a default AS400JDBCManagedDataSource object.
+ **/
+ public AS400JDBCManagedDataSource()
+ {
+ initializeTransient();
+ }
+
+ /**
+ Constructs an AS400JDBCManagedDataSource object to the specified serverName.
+ @param serverName The name of the IBM i system.
+ **/
+ public AS400JDBCManagedDataSource(String serverName)
+ {
+ this();
+
+ setServerName(serverName);
+ }
+
+ /**
+ Constructs an AS400JDBCManagedDataSource 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 AS400JDBCManagedDataSource(String serverName, String user, String password)
+ {
+ this();
+
+ setServerName(serverName);
+ setUser(user);
+ setPassword(password);
+ }
+
+
+ // Note: We do not provide a constructor that takes an AS400 object,
+ // because we need to capture the password so we can use it as part of the pool key.
+
+
+ /**
+ Constructs an AS400JDBCManagedDataSource object with the specified signon information
+ to use for SSL communications with the IBM i system.
+ @param serverName The name of the 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 AS400JDBCManagedDataSource(String serverName, String user, String password,
+ String keyRingName, String keyRingPassword)
+ {
+ this();
+
+ setSecure(true);
+
+ try
+ {
+ as400_ = new SecureAS400(as400_);
+ ((SecureAS400)as400_).setKeyRingName(keyRingName, keyRingPassword);
+ }
+ catch (PropertyVetoException pe) {} // will never happen
+
+ serialKeyRingName_ = keyRingName;
+
+ // 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);
+
+ setServerName(serverName);
+ setUser(user);
+ setPassword(password);
+ }
+
+
+ /**
+ Constructs an AS400JDBCManagedDataSource object from the specified Reference object
+ @param reference The reference to retrieve the DataSource properties from
+ **/
+ AS400JDBCManagedDataSource(Reference reference)
+ {
+ // Implementation note: This method is called from AS400JDBCObjectFactory.getObjectInstance
+
+ if (reference == null)
+ throw new NullPointerException("reference");
+
+ Properties properties = new Properties();
+
+ // 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();
+ // Note: Even though JDProperties has a "key ring" properties, we choose not to add them.
+ 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();
+ }
+ // Note that we allow the SECURE property to also get added to JDProperties in the loop below.
+
+ boolean isConnectionPoolDataSource = (this instanceof AS400JDBCManagedConnectionPoolDataSource);
+
+ 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.
+ // Perform special handling for properties that don't get included in JDProperties.
+
+ 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);
+ properties.put(property, value); // This value needs to go into JDProperties also.
+ }
+ else if (property.equals(PLAIN_TEXT_PASSWORD)) {
+ //set the password
+ setPassword(value);
+ }
+ else if (property.equals(PASSWORD))
+ {
+ if (reference.get(PLAIN_TEXT_PASSWORD) != null)
+ {
+ setPassword((String)reference.get(PLAIN_TEXT_PASSWORD).getContent());
+ }
+ else
+ {
+ // get the password back from the serialized char[]
+ if (value != null) {
+ serialPWBytes_ = value.toCharArray();
+ pwHashcode_ = xpwDeconfuse(serialPWBytes_).hashCode();
+ // decode the password and set it on the as400
+ as400_.setPassword(xpwDeconfuse(serialPWBytes_));
+ }
+ }
+ }
+ 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've already been handled prior to loop,
+ // and we don't want them added to JDProperties.
+ }
+ 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_TCP_NO_DELAY)) {
+ sockProps_.setTcpNoDelay((value.equals(TRUE_)? true : false));
+ }
+ else if (isConnectionPoolDataSource &&
+ AS400JDBCManagedConnectionPoolDataSource.isConnectionPoolProperty(property)) {
+ // Ignore this property, the subclass will consume it.
+ if (DEBUG) logDiagnostic("AS400JDBCManagedDataSource(Reference) is ignoring connection pool property \"" + property + "\"");
+ }
+ else { // It's neither a "socket property" nor a property that needs special handling.
+ properties.put(property, value); // Assume it goes into JDProperties.
+ }
+ } // 'while' loop
+
+ properties_ = new JDProperties(properties, null);
+ if (sockProps_.isAnyOptionSet()) { // only need to set if not default
+ as400_.setSocketProperties(sockProps_);
+ }
+
+ // 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);
+ }
+
+
+ /**
+ Verifies the health of the connection pool. For example: That the connection counts are consistent with the connection list lengths, and that all the daemons are still running.
+ Note: This method is provided for use as a diagnostic tool only. It temporarily "freezes" the connection pool while it collects statistics and examines the pool state.
+ @param logStatistics If true, additional information is logged.
+ @return true if connection pool exists and appears healthy; false otherwise.
+ **/
+ public boolean checkPoolHealth(boolean logStatistics)
+ {
+ if (poolManager_ == null) {
+ logWarning("Connection pool does not exist");
+ return false;
+ }
+ else return poolManager_.checkHealth(logStatistics);
+ }
+
+
+ // For exclusive use within this class and by AS400JDBCManagedConnectionPoolDataSource.
+ /**
+ Returns the database connection.
+ @return The connection.
+ @throws SQLException If a database error occurs.
+ **/
+ final AS400JDBCConnection createPhysicalConnection() throws SQLException
+ {
+ // If we have an AS400JDBCManagedConnectionPoolDataSource, delegate the connection creation.
+ if (cpds_ != null && cpds_ != this) {
+ return cpds_.createPhysicalConnection();
+ }
+ else
+ {
+ AS400 as400Object = null;
+
+ // 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()) {
+ as400Object = new SecureAS400(as400_);
+ }
+ else {
+ as400Object = new AS400(as400_);
+ }
+ if (sockProps_.isAnyOptionSet()) { // only need to set if not default
+ as400Object.setSocketProperties(sockProps_);
+ }
+
+ return createPhysicalConnection(as400Object);
+ }
+ }
+
+
+ // For exclusive use within this class and by AS400JDBCManagedConnectionPoolDataSource.
+ /**
+ Returns the database connection using the specified user and password.
+ @param user The database user.
+ @param password The database password.
+ @return The connection
+ @throws SQLException If a database error occurs.
+ **/
+ final AS400JDBCConnection createPhysicalConnection(String user, String password) throws SQLException
+ {
+ // Validate the parameters.
+ if (user == null)
+ throw new NullPointerException("user");
+ if (password == null)
+ throw new NullPointerException("password");
+
+ // If we have an AS400JDBCManagedConnectionPoolDataSource, delegate the connection creation.
+ if (cpds_ != null && cpds_ != this) {
+ return cpds_.createPhysicalConnection(user, password);
+ }
+ else
+ {
+ AS400 as400Object = null;
+
+ // 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()) {
+ as400Object = new SecureAS400(as400_);
+ }
+ else {
+ as400Object = new AS400(as400_);
+ }
+ try {
+ as400Object.setUserId(user);
+ as400Object.setPassword(password);
+ }
+ catch (PropertyVetoException pve) {} // will never happen
+
+ // Set GUI available on the new object to false if user turned prompting off.
+ try {
+ if (!isPrompt()) {
+ as400Object.setGuiAvailable(false);
+ }
+ }
+ catch (PropertyVetoException pve) {} // this will never happen
+
+ if (sockProps_.isAnyOptionSet()) { // only need to set if not default
+ as400Object.setSocketProperties(sockProps_);
+ }
+
+ return createPhysicalConnection(as400Object);
+ }
+ }
+
+
+ /**
+ Utility method to creates the database connection based on the signon and property information.
+ @param as400 The AS400 object used to make the connection.
+ @throws SQLException If a database error occurs.
+ **/
+ private AS400JDBCConnection createPhysicalConnection(AS400 as400) throws SQLException
+ {
+ AS400JDBCConnection connection = new AS400JDBCConnection();
+
+ connection.setProperties(new JDDataSourceURL(TOOLBOX_DRIVER + "//" + as400.getSystemName()), properties_, as400); // Note: This also does an AS400.connectService() to the database host server.
+
+ if (JDTrace.isTraceOn() || log_ != null) logInformation(ResourceBundleLoader.getText("AS400_JDBC_DS_CONN_CREATED"));
+ return connection;
+ }
+
+
+ //@PDA 550 - clone
+ /**
+ * Method to create a clone of AS400JDBCManagedDataSource. This does a shallow
+ * copy, with the exception of JDProperties, which also gets cloned.
+ */
+ public Object clone()
+ {
+ try
+ {
+ AS400JDBCManagedDataSource clone = (AS400JDBCManagedDataSource) 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()");
+ }
+ }
+
+
+ /**
+ Shuts down the connection pool in an orderly manner. Closes all connections in the pool.
+ @throws Throwable If an error occurs.
+ **/
+ public void closePool()
+ {
+ if (poolManager_ != null) poolManager_.closePool();
+ }
+
+
+ /**
+ 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);
+ }
+
+ /**
+ 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:
+ Valid values include:
+ Valid values include:
+ If pooling, the very first call to one of the getConnection() methods for this class will create and initialize the connection pool, and may have slow response. Therefore it is advisable for the application to make an initial "dummy" call to getConnection().
+ It is the responsibility of the caller to ultimately call Connection.close() to release the connection, even if the connection has become unusable.
+ @return The connection.
+ @throws SQLException If a database error occurs.
+ @see #setDataSourceName
+ **/
+ public Connection getConnection() throws SQLException
+ {
+ // Note: This method will return either an AS400JDBCConnection or an AS400JDBCConnectionHandle.
+ Connection connection;
+
+ if (dataSourceNameSpecified_ || (this instanceof AS400JDBCManagedConnectionPoolDataSource)) // A datasource name has been specified, so use pooling.
+ {
+ connection = getConnectionFromPool(null, null); // 'null' indicates "use default key".
+ // Returns a connection handle or null.
+
+ // The pooling implementation can return null if it can't produce a
+ // connection for the user. It is still our job to return a valid
+ // connection so drop back to returning a non-pooled connection at
+ // this point.
+ if (connection == null)
+ {
+ connection = createPhysicalConnection();
+ }
+ }
+ else // No datasource name has been specified, so return raw (unpooled) connection.
+ {
+ if (JDTrace.isTraceOn() || log_ != null) {
+ logWarning("No datasource name was specified, so connections will not be pooled");
+ }
+ // The connection is not linked to a pooled connection. Return a non-pooled connection.
+ connection = createPhysicalConnection();
+ }
+
+ if (DEBUG)
+ {
+ // Verify that the connection is for the correct user.
+ if (connection instanceof AS400JDBCConnection)
+ {
+ AS400JDBCConnection conn = (AS400JDBCConnection)connection;
+ String userForConn = conn.getUserName();
+ if (!userForConn.equalsIgnoreCase(cpds_.getUser())) {
+ logError("MDS.getConnection() is returning a connection with incorrect user: [" + userForConn +"]");
+ }
+ }
+ else if (connection instanceof AS400JDBCConnectionHandle) {
+ AS400JDBCConnectionHandle conn = (AS400JDBCConnectionHandle)connection;
+ String userForConn = conn.getUserName();
+ if (!userForConn.equalsIgnoreCase(cpds_.getUser())) {
+ logError("MDS.getConnection() is returning a connectionHandle with incorrect user: [" + userForConn +"]");
+ }
+ }
+ else {
+ logError("MDS.getConnection() is returning an instance of " + connection.getClass().getName());
+ }
+ }
+
+ return connection;
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ Returns a database connection using the specified user and password.
+ If pooling, the very first call to one of the getConnection() methods for this class will create and initialize the connection pool, and may have slow response. Therefore it is advisable for the application to make an initial "dummy" call to getConnection().
+ It is the responsibility of the caller to ultimately call Connection.close() to release the connection, even if the connection has become unusable.
+ @param user The database user.
+ @param password The database password.
+ @return The connection
+ @throws SQLException If a database error occurs.
+ @see #setDataSourceName
+ **/
+ public Connection getConnection(String user, String password) throws SQLException
+ {
+ // Note: This method will return either an AS400JDBCConnection or an AS400JDBCConnectionHandle.
+
+ // Validate the parameters.
+ if (user == null)
+ throw new NullPointerException("user");
+ if (password == null)
+ throw new NullPointerException("password");
+
+ Connection connection = null;
+ if (dataSourceNameSpecified_ ) // A datasource name has been specified, so use pooling.
+ {
+ // Note: xpwConfuse() generates different output each time it's called against the same password, so we can't use it bo build the pool key.
+ JDConnectionPoolKey key = new JDConnectionPoolKey(user, password.hashCode());
+ connection = getConnectionFromPool(key, password); // Returns a connection handle or null.
+
+ // The pooling implementation can return null if it can't produce a
+ // connection for the user. It is still our job to return a valid
+ // connection so drop back to returning a non-pooled connection at
+ // this point.
+ if (connection == null)
+ {
+ connection = createPhysicalConnection(user, password);
+ }
+ }
+ else // No datasource name has been specified, so return raw (unpooled) connection.
+ {
+ if (JDTrace.isTraceOn() || log_ != null) {
+ logWarning("No datasource name was specified, so connections will not be pooled");
+ }
+ // The connection is not linked to a pooled connection. Return a non-pooled connection.
+ connection = createPhysicalConnection(user, password);
+ }
+
+ if (DEBUG)
+ {
+ // Verify that the connection is for the correct user.
+ if (connection instanceof AS400JDBCConnection) {
+ AS400JDBCConnection conn = (AS400JDBCConnection)connection;
+ String userForConn = conn.getUserName();
+ if (!userForConn.equalsIgnoreCase(user)) {
+ logError("MDS.getConnection("+user+") is returning a connection with incorrect user: [" + userForConn +"]");
+ }
+ }
+ else if (connection instanceof AS400JDBCConnectionHandle) {
+ AS400JDBCConnectionHandle conn = (AS400JDBCConnectionHandle)connection;
+ String userForConn = conn.getUserName();
+ if (!userForConn.equalsIgnoreCase(user)) {
+ logError("MDS.getConnection("+user+") is returning a connectionHandle with incorrect user: [" + userForConn +"]");
+ }
+ }
+ else {
+ logError("MDS.getConnection() is returning an instance of " + connection.getClass().getName());
+ }
+ }
+
+ return connection;
+ }
+
+
+ /**
+ Returns a database connection from the pool, or null if the connection pool is at or near capacity.
+
+ @param key The connection pool key. 'null' indicates that the default key is to be used.
+ @return The connection. May return null if pool is at or near capacity.
+ @throws SQLException If a database error occurs.
+ **/
+ private final AS400JDBCConnectionHandle getConnectionFromPool(JDConnectionPoolKey key, String password) throws SQLException
+ {
+ // Note: This method generally returns an AS400JDBCPooledConnection. If the connection pool is full or nonexistent, it may return an (unpooled) AS400JDBCConnection.
+
+ AS400JDBCConnectionHandle connection = null;
+
+ if (!poolManagerInitialized_) {
+ initializeConnectionPool(); // this sets inUse_ to true
+ }
+
+ connection = poolManager_.getConnection(key, password);
+ if (connection == null)
+ {
+ if (JDTrace.isTraceOn() || log_ != null)
+ logWarning("Connection pool is at or near capacity, so returning a non-pooled connection");
+ // Note: If the 'enforceMaxPoolSize' property were set to true, then JDConnectionPoolManager.getConnection() would have thrown an exception if the pool is full and no connection is available. Since no exception was thrown, we can assume that the property is not set.
+ }
+
+ return connection;
+ }
+
+
+ // For exclusive use within this class and by JDConnectionPoolManager.
+ final JDConnectionPoolKey getConnectionPoolKey()
+ {
+ // See if we need to update our connection pool key.
+ if (connectionKeyNeedsUpdate_)
+ {
+ if (defaultConnectionPoolKey_ == null)
+ {
+ defaultConnectionPoolKey_ = new JDConnectionPoolKey(serialUserName_, pwHashcode_);
+ }
+ else // key already exists, so just update it
+ {
+ defaultConnectionPoolKey_.update(serialUserName_, pwHashcode_);
+ }
+ }
+
+ connectionKeyNeedsUpdate_ = false;
+ return defaultConnectionPoolKey_;
+ }
+
+
+ /**
+ Returns the value of the cursorSensitivity 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:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Possible values include:
+ Valid values include:
+ * 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);
+ }
+
+
+ // method required by javax.naming.Referenceable
+ /**
+ 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.
+ @throws NamingException If a naming error occurs in resolving the object.
+ **/
+ public Reference getReference() throws NamingException
+ {
+ 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_.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 (dataSourceName_ != null)
+ ref.add(new StringRefAddr(DATASOURCE_NAME, dataSourceName_));
+ if (description_ != null)
+ ref.add(new StringRefAddr(DESCRIPTION, description_));
+ ref.add(new StringRefAddr(SERVER_NAME, getServerName()));
+ ref.add(new StringRefAddr(USER, getUser()));
+ ref.add(new StringRefAddr(KEY_RING_NAME, serialKeyRingName_));
+ if (savePasswordWhenSerialized_) {
+ if (serialPWBytes_ != null)
+ ref.add(new StringRefAddr(PASSWORD, new String(serialPWBytes_)));
+ else
+ ref.add(new StringRefAddr(PASSWORD, null));
+ if (serialKeyRingPWBytes_ != null)
+ ref.add(new StringRefAddr(KEY_RING_PASSWORD, new String(serialKeyRingPWBytes_)));
+ else
+ ref.add(new StringRefAddr(KEY_RING_PASSWORD, null));
+ }
+ ref.add(new StringRefAddr(SAVE_PASSWORD, (savePasswordWhenSerialized_ ? TRUE_ : FALSE_)));
+
+ 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 value of the serverName property.
+ @return The system name.
+ **/
+ public String getServerName()
+ {
+ return as400_.getSystemName();
+ }
+
+
+ /**
+ Returns the level of tracing started on 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,
+ 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 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,
+ 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 long getSocketTimeout()
+ {
+ return getSoTimeout();
+ }
+
+
+ /**
+ Returns how the IBM i system sorts records before sending them to the
+ client.
+ @return The sort value.
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Possible values include:
+
+ 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 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();
+ }
+
+
+ /**
+ Logs an exception and message to the event log.
+ @param property The property to log.
+ @param value The property value to log.
+ **/
+ void logProperty(String property, String value)
+ {
+ // NOTE: JDTrace logs nothing unless JDTrace.isTraceOn() is true.
+ if (JDTrace.isTraceOn())
+ JDTrace.logProperty (this, property, value);
+ }
+
+ final void logDiagnostic(String text)
+ {
+ // Note: Currently this method is implemented identically to logInformation().
+ // At some future point, we may want to add unique behavior to it.
+ // In the meantime, it is a placeholder.
+ if (JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this, text);
+ if (log_ != null) log_.log(text);
+ }
+ }
+
+ final void logError(String text)
+ {
+ String msg = "ERROR: " + text;
+ JDTrace.logInformation (this, msg);
+ if (log_ != null) log_.log(msg);
+ else if (DEBUG) System.out.println(msg);
+ }
+
+ final void logException(String text, Exception e)
+ {
+ JDTrace.logException (this, text, e);
+ if (log_ != null) log_.log(text, e);
+ else if (DEBUG) {
+ System.out.println(text);
+ e.printStackTrace();
+ }
+ }
+
+
+ final void logInformation(String text)
+ {
+ // NOTE: JDTrace logs nothing unless JDTrace.isTraceOn() is true.
+ if (JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this, text);
+ if (log_ != null) log_.log(text);
+ }
+ }
+
+ final void logWarning(String text)
+ {
+ String msg = "WARNING: " + text;
+ JDTrace.logInformation (this, msg);
+ if (log_ != null) log_.log(msg);
+ else if (DEBUG) System.out.println(msg);
+ }
+
+ /**
+ Deserializes and initializes transient data.
+ @throws ClassNotFoundException If the class cannot be found.
+ @throws IOException If an I/O exception occurs.
+ **/
+ private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException
+ {
+ in.defaultReadObject();
+ initializeTransient();
+ }
+
+
+ /**
+ Sets the level of database access for the connection.
+ @param access The access level.
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+
+ Note: The properties of the specified datasource will override all similarly-named properties of this object. For example, if the specified datasource has a "serverName" property, then that value will be used by {@link #getConnection getConnection()}, and any value set via {@link #setServerName setServerName()} will be disregarded.
+
+ Note: If a dataSourceName is not specified, the {@link #getConnection getConnection()} methods will simply return non-pooled connections.
+ @param dataSourceName The data source name.
+ @throws ExtendedIllegalStateException If the data source is already in use.
+ **/
+ public void setDataSourceName(String dataSourceName)
+ {
+ final String property = DATASOURCE_NAME;
+
+ if (isInUse()) {
+ logError("Data source is already in use");
+ throw new ExtendedIllegalStateException(property, ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ if (dataSourceName == null)
+ throw new NullPointerException(property);
+
+ dataSourceName_ = dataSourceName;
+ dataSourceNameSpecified_ = true;
+
+ logProperty(property, 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)
+ {
+ if (truncation)
+ properties_.setString(JDProperties.DATA_TRUNCATION, TRUE_);
+ else
+ properties_.setString(JDProperties.DATA_TRUNCATION, FALSE_);
+ }
+
+ /**
+ Sets the date format used in date literals within SQL statements.
+ @param dateFormat The date format.
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Note: The specified PrintWriter might not be retained when an object is obtained via JNDI, that is, by a call to javax.naming.Context.lookup(). Therefore, use this method only on the DataSource object that is used directly by your application (rather than on the "template" DataSource object that was bound in JNDI).
+ @param writer The log writer; to disable, set to null.
+ @throws SQLException If a database error occurs.
+ **/
+ public void setLogWriter(PrintWriter writer) throws SQLException
+ {
+ writer_ = writer;
+ logProperty("logWriter", (writer_ == null ? "null" : writer_.toString()));
+
+ if (writer == null)
+ {
+ log_ = null;
+ }
+ else
+ {
+ 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)
+ {
+ Integer newValue = new Integer(mds);
+
+ properties_.setString(JDProperties.METADATA_SOURCE, newValue.toString());
+
+ }
+
+ //@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)
+ {
+ final String property = "naming";
+ if (naming == null)
+ throw new NullPointerException(property);
+ validateProperty(property, naming, JDProperties.NAMING);
+
+ properties_.setString(JDProperties.NAMING, naming);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "packageName";
+ if (packageName == null)
+ throw new NullPointerException(property);
+
+ properties_.setString(JDProperties.PACKAGE, packageName);
+ }
+
+ /**
+ 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 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 void setPackageAdd(boolean add)
+ {
+ if (add)
+ properties_.setString(JDProperties.PACKAGE_ADD, TRUE_);
+ else
+ properties_.setString(JDProperties.PACKAGE_ADD, FALSE_);
+ }
+
+ /**
+ 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 True if caching is used; false otherwise. The default value is false.
+ **/
+ public void setPackageCache(boolean cache)
+ {
+ if (cache)
+ properties_.setString(JDProperties.PACKAGE_CACHE, TRUE_);
+ else
+ properties_.setString(JDProperties.PACKAGE_CACHE, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ }
+
+ /**
+ 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)
+ {
+ final String property = "packageCriteria";
+
+ if (packageCriteria == null)
+ throw new NullPointerException(property);
+ validateProperty(property, packageCriteria, JDProperties.PACKAGE_CRITERIA);
+
+ properties_.setString(JDProperties.PACKAGE_CRITERIA, packageCriteria);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "packageError";
+ if (packageError == null)
+ throw new NullPointerException(property);
+ validateProperty(property, packageError, JDProperties.PACKAGE_ERROR);
+
+ properties_.setString(JDProperties.PACKAGE_ERROR, packageError);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "packageLibrary";
+ if (packageLibrary == null)
+ throw new NullPointerException(property);
+
+ properties_.setString(JDProperties.PACKAGE_LIBRARY, packageLibrary);
+ }
+
+ /**
+ Sets the 'password' property.
+ @param password The password.
+ **/
+ public void setPassword(String password)
+ {
+ final String property = "password";
+ if (password == null)
+ throw new NullPointerException(property);
+
+ char[] newSerialPWBytes = xpwConfuse(password);
+ if (!Arrays.equals(newSerialPWBytes, serialPWBytes_)) {
+ as400_.setPassword(password);
+ invalidate(getUser(), serialPWBytes_); // invalidate any pooled connections with old password
+ serialPWBytes_ = newSerialPWBytes;
+ pwHashcode_ = password.hashCode();
+
+ connectionKeyNeedsUpdate_ = true;
+ // Note: We deliberately do _not_ store the password into properties_.
+ }
+ logInformation(ResourceBundleLoader.getText("AS400_JDBC_DS_PASSWORD_SET"));
+ logProperty(property, "***");
+ }
+
+ /**
+ 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)
+ {
+ if (prefetch)
+ properties_.setString(JDProperties.PREFETCH, TRUE_);
+ else
+ properties_.setString(JDProperties.PREFETCH, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ if (prompt)
+ properties_.setString(JDProperties.PROMPT, TRUE_);
+ else
+ properties_.setString(JDProperties.PROMPT, FALSE_);
+
+ try
+ {
+ as400_.setGuiAvailable(prompt);
+ }
+ catch (PropertyVetoException vp) {} // this 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 AS400JDBCManagedDataSource 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 AS400JDBCManagedDataSource(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 AS400JDBCManagedDataSource 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 AS400JDBCManagedDataSource 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)
+ {
+ final String property = "proxyServer";
+ if (proxyServer == null)
+ throw new NullPointerException(property);
+
+ properties_.setString(JDProperties.PROXY_SERVER, proxyServer);
+ }
+
+ /**
+ Sets the "query optimize goal" property
+ @param goal - the optimization goal
+ Valid values include:
+ Valid values include:
+ * Valid values are -1 to MAX_STORAGE_LIMIT megabytes.
+ * The default value is -1 meaning there is no limit.
+ **/
+ public void setQueryStorageLimit(int limit)
+ {
+ String property = "queryStorageLimit";
+
+ if (limit < -1 || limit > MAX_STORAGE_LIMIT)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+
+ properties_.setString(JDProperties.QUERY_STORAGE_LIMIT, Integer.toString(limit));
+ }
+
+ /**
+ 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)
+ {
+ final String property = "remarks";
+ if (remarks == null)
+ throw new NullPointerException(property);
+ validateProperty(property, remarks, JDProperties.REMARKS);
+
+ properties_.setString(JDProperties.REMARKS, remarks);
+ }
+
+ /**
+ Sets the "rollback cursor hold" property
+ @param hold True to hold cursor across rollbacks. The default value is false.
+ **/
+ public void setRollbackCursorHold(boolean hold)
+ {
+ if (hold)
+ properties_.setString(JDProperties.ROLLBACK_CURSOR_HOLD, TRUE_);
+ else
+ properties_.setString(JDProperties.ROLLBACK_CURSOR_HOLD, FALSE_);
+ }
+
+ /**
+ 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");
+
+ properties_.setString(JDProperties.SECONDARY_URL, url);
+ }
+
+ //@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.
+ @throws ExtendedIllegalStateException If the data source was constructed with a keyring and secure is false.
+ **/
+ public void setSecure(boolean secure)
+ {
+ // Do not allow user to change to not secure if they constructed the data source with
+ // a keyring.
+ if (!secure && isSecure_)
+ {
+ throw new ExtendedIllegalStateException("secure",
+ ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ // Keep local copy for convenience.
+ isSecure_ = secure;
+
+ if (secure)
+ properties_.setString(JDProperties.SECURE, TRUE_);
+ else
+ properties_.setString(JDProperties.SECURE, FALSE_);
+ }
+
+
+ //@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)
+ {
+ if (secureCurrentUser)
+ properties_.setString(JDProperties.SECURE_CURRENT_USER, TRUE_);
+ else
+ properties_.setString(JDProperties.SECURE_CURRENT_USER, FALSE_);
+ }
+
+
+ /**
+ Sets the serverName property.
+ @param serverName The system name.
+ @throws ExtendedIllegalStateException If the data source is already in use.
+ **/
+ public void setServerName(String serverName)
+ {
+ final String property = SERVER_NAME;
+
+ if (isInUse()) {
+ logError("Data source is already in use");
+ throw new ExtendedIllegalStateException(property, ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ if (serverName == null)
+ throw new NullPointerException(property);
+
+ // Save away the name to serialize.
+ serialServerName_ = serverName; // Note: There is no associated JDProperties entry.
+
+ try
+ {
+ as400_.setSystemName(serverName);
+ }
+ catch (PropertyVetoException pv) {} // will never happen
+
+ connectionKeyNeedsUpdate_ = true;
+
+ logProperty(property, as400_.getSystemName());
+ }
+
+
+ /**
+ 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,
+ 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)
+ {
+ properties_.setString(JDProperties.TRACE_SERVER, Integer.toString(traceCategories));
+ }
+
+ /**
+ 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,
+ 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);
+ }
+
+ /**
+ 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:
+
+ 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)
+ {
+ final String property = "savePasswordWhenSerialized";
+
+ savePasswordWhenSerialized_ = savePassword;
+
+ logProperty(property, String.valueOf(savePasswordWhenSerialized_)); //@jvm13 Boolean.toString(savePasswordWhenSerialized_));
+ }
+
+ //@STIMEOUT
+ /**
+ * This property enables/disables socket timeout with the
+ * specified value in milliseconds. A timeout value must be
+ * greater than zero, a value of zero for this property indicates
+ * infinite timeout.
+ * @param milliseconds The socket timeout option value.
+ **/
+ public void setSocketTimeout(int milliseconds)
+ {
+ setSoTimeout(milliseconds);
+ }
+
+ /**
+ 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");
+
+ properties_.setString(JDProperties.SORT_LANGUAGE, language);
+ }
+
+ /**
+ 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");
+
+ properties_.setString(JDProperties.SORT_TABLE, table);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "sortWeight";
+ if (sortWeight == null)
+ throw new NullPointerException(property);
+
+ validateProperty(property, sortWeight, JDProperties.SORT_WEIGHT);
+
+ properties_.setString(JDProperties.SORT_WEIGHT, sortWeight);
+ }
+
+ /**
+ 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)
+ {
+ if (threadUsed)
+ properties_.setString(JDProperties.THREAD_USED, TRUE_);
+ else
+ properties_.setString(JDProperties.THREAD_USED, FALSE_);
+ }
+
+ /**
+ Sets the time format used in time literals with SQL statements.
+ @param timeFormat The time format.
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ Valid values include:
+ * Valid values include:
+ Valid values include:
+ *
+* AS400JDBCPooledConnection objects generate the following events:
+*
+ * @param listener an component which implements the
+ * @param listener the component which implements the
+ *
+ * The AS400JDBCPreparedStatement class precompiles and stores an SQL statement.
+ * This provides the ability to efficiently run the statement multiple times. In
+ * addition, the statement may contain parameters. Use
+ * Connection.prepareStatement() to create new PreparedStatement objects.
+ *
+ *
+ * When setting input parameter values, the caller must specify types that are
+ * compatible with the defined SQL type of the input parameter. For example, if
+ * the input parameter has SQL type INTEGER, then the caller must call setInt()
+ * to set the IN parameter value. If arbitrary type conversions are required,
+ * then use setObject() with a target SQL type.
+ *
+ *
+ * For method that sets parameters, the application should not modify the
+ * parameter value until after the execute completes. Modifying a value between
+ * the setXXXX method and the execute method may result in unpredictable
+ * behavior.
+ **/
+//
+// Implementation notes:
+//
+// 1. See implementation note in AS400JDBCStatement.java about
+// "private protected" methods.
+//
+// @F2A
+// 2. We need to support ?=CALL statements. This is where the stored
+// procedure returns an INTEGER value, and we treat it as the
+// first parameter marker. The database and host server support
+// the return value, but not as a parameter marker. Consequently,
+// we have to fake it as the first parameter marker. If this appears,
+// in the SQL statement, we strip it off and maintain this separately.
+// Of course in that case we are always mapping the caller's parameter
+// indices to the database's indices by decrementing by 1 as needed.
+//
+// @G8c
+// 3. If there is a return value (ie ?=call xxxx) and the parameter
+// index is 1 then return data for the return value (always an Integer).
+// If not, decrement the parm index by one because internally the return
+// value doesn't count. If there is no return value the count is correct
+// so don't do anything in that case. Also, the database supports returning
+// only integers so the metadata will always be an SQLInteger.
+//
+public class AS400JDBCPreparedStatement extends AS400JDBCStatement implements
+ PreparedStatement {
+ static final String copyright2 = "Copyright (C) 1997-2006 International Business Machines Corporation and others.";
+
+ private boolean dataTruncation_; // @B5A
+ private int descriptorHandle_;
+ boolean executed_; // private protected
+ private boolean outputParametersExpected_;
+ int parameterCount_; // private protected
+ int parameterInputCount_; // private protected //@array4
+ boolean batchExecute_; // private protected @G9A
+ private boolean executingBatchedStatement_ = false; // Flag to prevent
+ // clearParameters from
+ // causing execute
+ // exception @DAA
+ private int[] parameterLengths_;
+ private int[] parameterOffsets_;
+ private boolean[] parameterNulls_;
+ private boolean[] parameterDefaults_; // @EIA
+ private boolean[] parameterUnassigned_; // @EIA
+ private String[] parameterNames_; // @pda jdbc40
+ // @re-prep move to statement JDServerRow JDServerRow parameterRow_; //
+ // private protected
+ Vector batchParameterRows_; // private protected @G9A
+ private int parameterTotalSize_;
+ private int indicatorTotalSize_; // @array Used with array containing data
+ // only. Is total size of all indicators
+ // (including array element indicators)
+ private int headerTotalSize_; // @array Used to calculate size of stream
+ // header
+ boolean[] parameterSet_; // private protected
+ private boolean prepared_;
+ private JDServerRow resultRow_;
+ SQLInteger returnValueParameter_; // private protected @F2A
+ JDSQLStatement sqlStatement_; // @G4c (used by callable statement)
+ boolean useReturnValueParameter_; // private protected @F2A
+ private int maxToLog_ = 10000; // Log value of parameter markers up to this
+ // length // @H1A
+ private boolean containsArrayParameter_ = false; /* @G7A */
+
+ private int containsLocator_ = LOCATOR_UNKNOWN;
+ private static final int LOCATOR_UNKNOWN = -1;
+ private static final int LOCATOR_NOT_FOUND = 0;
+ private static final int LOCATOR_FOUND = 1;
+
+ private static final short INDICATOR_NULL = -1; // @EIA
+ private static final short INDICATOR_DEFAULT = -5; // @EIA
+ private static final short INDICATOR_UNASSIGNED = -7; // @EIA
+ private boolean isjvm16Synchronizer;// @dmy
+ private static boolean isjvm16SynchronizerStatic;// @dmy
+ static {
+ // Changed 2/21/2011 to not use unless the JDBC.jvm16Synchronize property is
+ // true. @C6A
+
+ /*
+ * Here is some information from service about this error.
+ *
+ * Yes, this trace code was added for a very ugly issue that showed up when
+ * customers started moving to Java 6. While trying to debug it, we found
+ * that the trace points ended up changing the behavior, so they were
+ * altered to trace to a dummy stream so that it would workaround Sun's bug.
+ * The CPS discussion item was 7LXN87.
+ *
+ * Here's the contents of our KB doc on the issue:
+ *
+ * Abstract A problem with the Sun HotSpot Server in the 1.6 JDK causes a
+ * variety of errors.
+ *
+ * Problem Summary: A problem was introduced into the version 1.6 JDK (Java
+ * Development Kit) and JRE (Java Runtime Environment) from Sun. The problem
+ * was introduced somewhere between update number 7 and update 12, which can
+ * cause a number of problems. Java version 1.6.0_7 works; however, version
+ * 1.6.0_12 produces the errors. The problem is specific to the HotSpot
+ * Server which is something like an optimizing compiler that is designed to
+ * provide the best operating speed for long-running applications similar to
+ * a Web server. The problem seems to always manifest itself by 'removing'
+ * parameters that had been bound to a statement. However, it is not
+ * possible to know that this has occurred without tracing the application.
+ * The outward symptoms are exceptions which will vary depending on what
+ * data is missing. The common errors that have been reported are as
+ * follows:
+ *
+ * SQLException: Descriptor index not valid CPD4374 - Field HVR000n and
+ * value N not compatible. <-- where N might a variety of different numbers
+ * SQL0302 - Conversion error on host variable or parameter *N. <-- where n
+ * might a variety of different numbers SQL0406 - Conversion error on
+ * assignment to column N. <-- where N might a variety of different numbers
+ *
+ * Resolution: The problem has been reported to Sun; however, at this time,
+ * no fix is available from them. We have found three ways to circumvent the
+ * problem:
+ *
+ * 1. Do not use JDK 1.6. 2. Use JVM property -client (this turns off
+ * performance code in Sun Hotspot). 3. Use JVM property
+ * -XX:CompileCommand=exclude
+ * ,com/ibm/as400/access/AS400JDBCPreparedStatement,commonExecuteBefore
+ * (more selectively, turn off part of Hotspot). 4. Use the latest version
+ * of jt400.jar (currently 6.6). Additional trace points that were added
+ * while searching for the source of the problem appear to have changed the
+ * Hotspot behavior.
+ *
+ *
+ *
+ * Update 2/24/2011. This was probably a problem with the buffer
+ * synchonization. Before JTOpen 7.1, a flag was set to indicate that a
+ * buffer was available. This flag did not utilize any synchronization. In
+ * JTOpen 7.1, the buffer management code was restructure to used
+ * synchronzation.
+ *
+ * A recreate for the original problem was found. It failed using the JTOpen
+ * 6.4 jar. We then used a jar with the change the set the default
+ * isjvm16SynchronizerStatic to false and set the default value of the
+ * property to false. The problem did not occur with the jar file.
+ */
+
+ // Temporary fix for jvm 1.6 memroy stomp issue. (remove //@dmy code when
+ // jvm issue is resolved)
+ // This fix will just trace a few extra traces to a dummy stream
+ // if system property or jdbc property is set to false then extra trace is
+ // not executed
+ // null value for system property means not specified...so true by default
+ String jvm16Synchronize = SystemProperties
+ .getProperty(SystemProperties.JDBC_JVM16_SYNCHRONIZE); // @dmy
+ isjvm16SynchronizerStatic = false; // @dmy //false by default @C6C
+ if ((jvm16Synchronize != null)
+ && (Boolean.valueOf(jvm16Synchronize.trim()).booleanValue() == true)) {
+ try { // @dmy
+ Class.forName("java.sql.SQLXML"); // @dmy
+ isjvm16SynchronizerStatic = true; // @dmy
+ } catch (Exception e) { // @dmy
+ isjvm16SynchronizerStatic = false; // @dmy
+ }
+
+ } else {
+ // @dmy
+ isjvm16SynchronizerStatic = false; // @dmy
+ }
+
+ }
+ // @C6C -- Changed to remove the dummy PrimWriter. The dummy PrintWriter uses
+ // a
+ // 16k buffer of storage. This causes storage problems when a lot of
+ // statements are
+ // cached. Instead we'll use the write(byte[]) method instead of the buffered
+ // print writer
+ //
+ // @dmy private dummy outputstream
+ OutputStream dummyOutputStream = new OutputStream() {
+ int b1 = 0;
+
+ public synchronized void write(int b) throws IOException {
+ b1 = b;
+ }
+
+ };
+
+ // Any method that can deal with extremely large data values must be prepared
+ // to deal with them in blocks instead of as one giant unit. This value is
+ // used to determine the size of each block. Eventually, we might externalize
+ // this value so that users can set it as they see fit.
+ static final int LOB_BLOCK_SIZE = 1000000; // @pdc Match Native JDBC Driver
+ // for IBM i
+
+ /**
+ * Constructs an AS400JDBCPreparedStatement 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 prefetch
+ * Indicates if prefetching data.
+ * @param sqlStatement
+ * The SQL statement.
+ * @param outputParametersExpected
+ * Indicates if output parameters are expected.
+ * @param packageCriteria
+ * The package criteria.
+ * @param resultSetType
+ * The result set type.
+ * @param resultSetConcurrency
+ * The result set concurrency.
+ * @param resultSetHoldability
+ * The result set holdability.
+ * @param autoGeneratedKeys
+ * The auto-generated keys requested
+ * @exception SQLException
+ * If the SQL statement contains a syntax error or an error
+ * occurs.
+ **/
+ AS400JDBCPreparedStatement(AS400JDBCConnection connection, int id,
+ JDTransactionManager transactionManager, JDPackageManager packageManager,
+ String blockCriteria, int blockSize, boolean prefetch,
+ JDSQLStatement sqlStatement, boolean outputParametersExpected,
+ String packageCriteria, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability, // @G4A
+ int autoGeneratedKeys) // @G4A
+ throws SQLException {
+ super(connection, id, transactionManager, packageManager, blockCriteria,
+ blockSize, prefetch, packageCriteria, resultSetType,
+ resultSetConcurrency, resultSetHoldability, autoGeneratedKeys);
+
+ // @dmy
+ // Temporary fix for jvm 1.6 memroy stomp issue. (remove //@dmy code when
+ // jvm issue is resolved)
+ // This fix will just trace a few extra traces to a dummy stream
+ // if system property or jdbc property is set to false then extra trace is
+ // not executed
+ // null value for system property means not specified...so true by default
+ isjvm16Synchronizer = isjvm16SynchronizerStatic;
+ if (connection_.getProperties().getBoolean(JDProperties.JVM16_SYNCHRONIZE)) // @dmy
+ isjvm16Synchronizer = true; // @dmy@C6C
+
+ batchExecute_ = false; // @G9A
+ outputParametersExpected_ = outputParametersExpected;
+ parameterCount_ = sqlStatement.countParameters();
+ parameterInputCount_ = 0; // @array4 calculate while we prepare
+ parameterLengths_ = new int[parameterCount_];
+ parameterNulls_ = new boolean[parameterCount_];
+ parameterDefaults_ = new boolean[parameterCount_]; // @EIA
+ parameterUnassigned_ = new boolean[parameterCount_]; // @EIA
+ parameterOffsets_ = new int[parameterCount_];
+ parameterSet_ = new boolean[parameterCount_];
+ sqlStatement_ = sqlStatement;
+ useReturnValueParameter_ = sqlStatement.hasReturnValueParameter(); // @F2A
+
+ if (useReturnValueParameter_) // @F2A
+ returnValueParameter_ = new SQLInteger(connection_.getVRM(), settings_); // @F2A
+ // //@trunc3
+
+ if (JDTrace.isTraceOn()) { // @D1A @F2C
+ JDTrace
+ .logInformation(this, "isjvm16Synchronizer=" + isjvm16Synchronizer); // @C6A
+ JDTrace.logInformation(this, "Preparing [" + sqlStatement_ + "]"); // @D1A
+ if (useReturnValueParameter_) // @F2A
+ JDTrace.logInformation(this,
+ "Suppressing return value parameter (?=CALL)"); // @F2A
+ } // @F2A
+
+ // Do not allow statements to be immediately
+ // executed. If we did not do this, then some
+ // statements would get executed at prepare time.
+ allowImmediate_ = false;
+
+ // Prepare.
+ prepared_ = true;
+ // @L1A Added try catch block around commonPrepare() for JTOpen Bug #3605
+ // Statement not fully closed on error.
+ // If an error occurs in the preparing of the statement, we need to close
+ // any resources used by the PreparedStatement object.
+ try {
+ resultRow_ = commonPrepare(sqlStatement_);
+ } catch (SQLException e) {
+ close();
+ throw e;
+ }
+ executed_ = false;
+
+ dataTruncation_ = connection.getProperties().getBoolean(
+ JDProperties.DATA_TRUNCATION);
+
+ clearParameters();
+ }
+
+ // JDBC 2.0
+ /**
+ * Adds the set of parameters to the current batch.
+ *
+ * @exception SQLException
+ * If the statement is not open or an input parameter has not
+ * been set.
+ **/
+ public void addBatch() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+ Object[] parameters = new Object[parameterCount_];
+ for (int i = 0; i < parameterCount_; ++i) {
+ // Statements with output or inout parameters are not allowed in the
+ // batch.
+ if (parameterRow_.isOutput(i + 1))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // If an input parameter is not set, we throw an exception.
+ if (!parameterSet_[i])
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_COUNT_MISMATCH);
+
+ // @KBA Need to check for locators even if the parameter is null
+ // If we don't check for locators and the first row had locator fields
+ // that are all null, the LOCATOR_FOUND
+ // flag was not being set. This meant that we thought we could batch
+ // when executeBatch() was called. We cannot
+ // batch when locators are being used.
+ SQLData sqlData = parameterRow_.getSQLData(i + 1); // @KBA
+ // Save the parameter in the array. If it's null, just leave it null.
+ if (!parameterNulls_[i]) {
+ // @KBD SQLData sqlData = parameterRow_.getSQLData(i+1);
+ // For default and unassigned extended indicator values, we use Byte
+ // to contain the indicator flag
+ if (parameterDefaults_[i]) // @EIA
+ parameters[i] = new Byte("1"); // default //@EIA
+ else if (parameterUnassigned_[i]) // @EIA
+ parameters[i] = new Byte("2"); // unassigned //@EIA
+ else
+ // @EIA
+ parameters[i] = sqlData.getObject();
+ // @KBD if(containsLocator_ == LOCATOR_UNKNOWN)
+ // @KBD {
+ // @KBD int sqlType = sqlData.getSQLType();
+ // @KBD if (sqlType == SQLData.CLOB_LOCATOR ||
+ // @KBD sqlType == SQLData.BLOB_LOCATOR ||
+ // @KBD sqlType == SQLData.DBCLOB_LOCATOR)
+ // @KBD {
+ // @KBD containsLocator_ = LOCATOR_FOUND;
+ // @KBD }
+ // @KBD }
+ }
+
+ // @KBA check to see if the parameter is a locator field
+ if (containsLocator_ == LOCATOR_UNKNOWN) // @KBA
+ { // @KBA
+ int sqlType = sqlData.getSQLType(); // @KBA
+ if (sqlType == SQLData.CLOB_LOCATOR || // @KBA
+ sqlType == SQLData.BLOB_LOCATOR || // @KBA
+ sqlType == SQLData.DBCLOB_LOCATOR || // @KBA //@pdc jdbc40
+/* ifdef JDBC40 */
+ sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
+/* endif */
+
+
+
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ { // @KBA
+ containsLocator_ = LOCATOR_FOUND; // @KBA
+ } // @KBA
+ } // @KBA
+ }
+ if (containsLocator_ == LOCATOR_UNKNOWN)
+ containsLocator_ = LOCATOR_NOT_FOUND;
+
+ if (batch_ == null)
+ batch_ = new Vector(); // @P0A
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "addBatch()");
+ batch_.addElement(parameters);
+ }
+ }
+
+ // JDBC 2.0
+ /**
+ * Adds an SQL statement to the current batch of SQL statements.
+ *
+ *
+ * Do not use this form of addBatch() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement to be added to the current batch. This can be
+ * any SQL statement that does not return a result set.
+ * @exception SQLException
+ * This exception is always thrown.
+ **/
+ public void addBatch(String sql) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @B1C
+ }
+
+ // @BAA
+ /**
+ * Creates or changes the descriptor, which describes the parameter marker
+ * format.
+ *
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ private void changeDescriptor() throws SQLException {
+ // If a parameter that is not an input parameter has
+ // not been set, we still include it in the format.
+ //
+ // Note that we set the native type, length, scale and
+ // precision of each parameter in the descriptor.
+ // That means that if the user sets a new parameter
+ // value that changes one of these, then the
+ // descriptor needs to be changed.
+ //
+ DBSQLDescriptorDS request2 = null; // @P0C
+ try {
+ descriptorHandle_ = id_;
+ // @P0CDBSQLDescriptorDS request2 = new DBSQLDescriptorDS
+ // (DBSQLDescriptorDS.FUNCTIONID_CHANGE_DESCRIPTOR,
+ // @P0C id_, 0, descriptorHandle_);
+ request2 = DBDSPool.getDBSQLDescriptorDS(
+ DBSQLDescriptorDS.FUNCTIONID_CHANGE_DESCRIPTOR, id_, 0,
+ descriptorHandle_); // @P0C
+
+ DBDataFormat parameterMarkerDataFormat;
+ if (connection_.useExtendedFormats()) {
+ // @540 We are going to continue using DBExtendedDataFormat for this
+ // part. We use an empty string for the parameter name so we don't need
+ // 128 bytes
+ parameterMarkerDataFormat = new DBExtendedDataFormat(parameterCount_);
+ } else
+ parameterMarkerDataFormat = new DBOriginalDataFormat(parameterCount_);
+ request2.setParameterMarkerDataFormat(parameterMarkerDataFormat);
+
+ parameterMarkerDataFormat.setConsistencyToken(1);
+ parameterMarkerDataFormat.setRecordSize(parameterTotalSize_);
+
+ if (isjvm16Synchronizer) {
+ try {
+ dummyOutputStream
+ .write(("!!!changeDescriptor: totalParameterLength_ = " + parameterTotalSize_)
+ .getBytes()); // @dmy@C6C
+ } catch (Exception e) {
+
+ }
+ }
+
+ for (int i = 0; i < parameterCount_; ++i) {
+ SQLData sqlData = parameterRow_.getSQLData(i + 1);
+
+ parameterMarkerDataFormat.setFieldDescriptionLength(i);
+ if (sqlData.getNativeType() == SQLData.NATIVE_ARRAY) // @array
+ { // @array
+ int arrayLen = ((SQLArray) sqlData).getArrayCount(); // @array
+ if (arrayLen > 0) // @array
+ parameterMarkerDataFormat.setFieldLength(i, parameterLengths_[i]
+ / arrayLen); // @array
+ else
+ // @array
+ parameterMarkerDataFormat.setFieldLength(i, parameterLengths_[i]); // @array
+ } // @array
+ else // @array
+ {
+ parameterMarkerDataFormat.setFieldLength(i, parameterLengths_[i]);
+ }
+ parameterMarkerDataFormat.setFieldCCSID(i,
+ parameterRow_.getCCSID(i + 1));
+
+ parameterMarkerDataFormat.setFieldNameLength(i, 0);
+ parameterMarkerDataFormat.setFieldNameCCSID(i, 0);
+ parameterMarkerDataFormat.setFieldName(i, "", connection_.converter_); // @P0C
+
+ // @array (arrays sent in as the element type and zda will know they are
+ // arrays)
+ if (sqlData.getNativeType() == SQLData.NATIVE_ARRAY) // @array
+ { // @array
+ parameterMarkerDataFormat.setFieldSQLType(i,
+ (short) (((SQLArray) sqlData).getElementNativeType() | 0x0001)); // @array
+ } // @array
+ else {
+ parameterMarkerDataFormat.setFieldSQLType(i,
+ (short) (sqlData.getNativeType() | 0x0001));
+ }
+
+ parameterMarkerDataFormat.setFieldScale(i, (short) sqlData.getScale());
+ parameterMarkerDataFormat.setFieldPrecision(i,
+ (short) sqlData.getPrecision());
+ if (isjvm16Synchronizer) {
+ try {
+ dummyOutputStream.write(("!!!changeDescriptor: Parameter "
+ + (i + 1) + " length = " + parameterLengths_[i]).getBytes()); // @C6C
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+ connection_.send(request2, descriptorHandle_);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Descriptor " + descriptorHandle_
+ + " created or changed");
+ } catch (DBDataStreamException e) {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ } finally { // @P0C
+
+ if (isjvm16Synchronizer) {
+ if (request2 != null) {
+ try {
+ dummyOutputStream
+ .write(("!!!changeDescriptor.inUser_(false): request2-id=" + request2
+ .hashCode()).getBytes()); // @C6C
+ } catch (Exception e) {
+ }
+
+ }
+ }
+ if (request2 != null) {
+ request2.returnToPool();
+ request2 = null;
+ } // @P0C
+ }
+ }
+
+ /**
+ * Releases the resources used by the current input parameter values. In
+ * general, input parameter values remain in effect for repeated executions of
+ * the prepared statement. Setting an input parameter value to a new value
+ * automatically clears its previous value.
+ *
+ * @exception SQLException
+ * If the statement is not open.
+ **/
+ public void clearParameters() throws SQLException {
+ synchronized (internalLock_) { // @F1A
+ checkOpen();
+
+ for (int i = 0; i < parameterCount_; ++i) {
+ // @E1D parameterLengths_[i] = 0;
+ parameterNulls_[i] = false;
+ parameterDefaults_[i] = false; // @EIA
+ parameterUnassigned_[i] = false; // @EIA
+ // @E1D parameterOffsets_[i] = 0;
+ parameterSet_[i] = false;
+ }
+
+ // @E1D parameterTotalSize_ = 0;
+
+ if (useReturnValueParameter_) // @F2A
+ returnValueParameter_.set(0); // @F2A
+ }
+ }
+
+ /**
+ * Releases the prepared statement's resources immediately instead of waiting
+ * for them to be automatically released. This closes the current result set.
+ *
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ public void close() throws SQLException {
+ synchronized (internalLock_) { // @F1A
+ // 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;
+
+ // If a descriptor was created somewhere along
+ // the lines, then delete it now.
+ if (descriptorHandle_ != 0) {
+ // @P0CDBSQLDescriptorDS request = new DBSQLDescriptorDS (
+ // @P0C DBSQLDescriptorDS.FUNCTIONID_DELETE_DESCRIPTOR,
+ // @P0C id_, 0, descriptorHandle_);
+ DBSQLDescriptorDS request = null; // @P0C
+ try { // @P0C
+ request = DBDSPool.getDBSQLDescriptorDS(
+ DBSQLDescriptorDS.FUNCTIONID_DELETE_DESCRIPTOR, id_, 0,
+ descriptorHandle_); // @P0C
+
+ connection_.send(request, descriptorHandle_);
+ } finally { // @P0C
+ if (isjvm16Synchronizer) {
+ try {
+ if (request != null) {
+ dummyOutputStream
+ .write(("!!!close.inUser_(false): request-id=" + request
+ .hashCode()).getBytes()); // @C6C
+ }
+ } catch (Exception e) {
+
+ }
+ }
+ if (request != null) {
+ request.returnToPool();
+ request = null;
+ } // @P0C
+ }
+
+ descriptorHandle_ = 0;
+ }
+
+ super.close();
+ }
+ }
+
+ /**
+ * Performs common operations needed after an execute.
+ *
+ * @param sqlStatement
+ * The SQL statement.
+ * @param reply
+ * The execute reply.
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ void commonExecuteAfter(JDSQLStatement sqlStatement, DBReplyRequestedDS reply) // private
+ // protected
+ throws SQLException {
+ super.commonExecuteAfter(sqlStatement, reply);
+
+ if (prepared_) {
+
+ DBData resultData = null;
+ if (outputParametersExpected_)
+ resultData = reply.getResultData();
+
+ // Store the output parameters, if needed.
+ if ((outputParametersExpected_) && (resultData != null)) {
+ parameterRow_.setServerData(resultData);
+ parameterRow_.setRowIndex(0);
+ }
+
+ // Handle the return value parameter, if needed. @F2A
+ try { // @F2A
+ if (useReturnValueParameter_) // @F2A
+ returnValueParameter_.set(reply.getSQLCA().getErrd(1)); // @F2A //@G3C
+ } // @F2A
+ catch (DBDataStreamException e) { // @F2A
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e); // @F2A
+ } // @F2A
+ }
+ }
+
+ /**
+ * 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 {
+ super.commonExecuteBefore(sqlStatement, request);
+ int requestLengthOffset = 0; /*@K3A*/
+ int initialRawOffset = 0; /*@K3A*/
+ if (prepared_) {
+ // Close the result set before executing again.
+ closeResultSet(JDCursor.REUSE_YES);
+
+ // Validate each parameters. If a parameter is not an
+ // input parameter, then it is okay for it not to have been
+ // set. However, if an input parameter was not set,
+ // we throw an exception.
+ boolean outputExpected_ = false; // @K2A We do not want to increment our
+ // row index in commonExecuteAfter() if
+ // there are no output parameters
+ parameterInputCount_ = 0; // Initialize before incrementing below. @G1
+ for (int i = 0; i < parameterCount_; ++i) {
+
+ // We don't need to validate the parameters if executing a batched
+ // statement.
+ // The parameter were validated during addBatch.
+ // If we attempt to validate, this will fail when
+ // clearParameters is called immediately before executeBatch().
+ // Problem reported via CPS 8KLGCZ August 2011 @DAA
+ if (!executingBatchedStatement_) {
+
+ if (!parameterSet_[i] && parameterRow_.isInput(i + 1)) {
+ JDError.throwSQLException(this,
+ JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ }
+ }
+ if (parameterRow_.isOutput(i + 1)) // @K2A
+ outputExpected_ = true; // @K2A
+ if (parameterRow_.isInput(i + 1)) // @array4
+ parameterInputCount_++; // @array4
+ }
+
+ if (!outputExpected_) // @K2A
+ outputParametersExpected_ = false; // @K2A
+
+ // Create the descriptor if needed. This should only
+ // be done once (on the first execute for the prepared
+ // statement).
+
+ // This needs to be done every time when there are array parameters.
+ // This is because the size of the array might change each time
+ // execute is called. @G7C
+
+ if (((parameterCount_ > 0) && (descriptorHandle_ == 0))
+ || ((parameterCount_ > 0) && containsArrayParameter_)) { /* @G7A */
+ // Reset the row index when reusing the parameter row. @G7A
+ parameterRow_.setRowIndex(-1);
+ // Get the offset and length for each parameter.
+ // We just use the information that came in the parameter
+ // marker format from reply for the prepare.
+ parameterTotalSize_ = 0;
+ indicatorTotalSize_ = 0; // @array
+ headerTotalSize_ = 2; // @array start with 2 since column count is 2
+ // bytes
+ for (int i = 0; i < parameterCount_; ++i) {
+ if (!parameterRow_.containsArray_ || parameterRow_.isInput(i + 1)) // @array4
+ {
+ SQLData sqlData = parameterRow_.getSQLData(i + 1); // @array
+ // boolean arrayIndicatorSet = false; //@array
+ if (sqlData.getType() == java.sql.Types.ARRAY) // @array
+ {
+ // Set the flag so that we still enter this code when
+ // the descriptor handle is not zero @G7A
+ containsArrayParameter_ = true;
+
+ int arrayLen = ((SQLArray) sqlData).getArrayCount(); // @array
+ // @G2A
+ int elementSize = parameterRow_.getArrayDataLength(i + 1); // @G2A
+ if (parameterNulls_[i] || parameterDefaults_[i]
+ || parameterUnassigned_[i]) // @array
+ headerTotalSize_ += 4; // @array space for x9911ffff
+ else
+ headerTotalSize_ += 12; // @array (array column requires 12
+ // bytes in header x9911) //@array2
+ parameterLengths_[i] = elementSize * arrayLen; // @array 0, 1, or
+ // more
+ // datatype-length
+ // blocks
+ indicatorTotalSize_ += (arrayLen * 2);// @array@G2A
+ } else {
+ // non array value
+ headerTotalSize_ += 8; // @array (assuming row has array. x9912 is
+ // length 8)
+ // Set non-array length, avoiding any unnecessary multiplication
+ // @G2A
+ parameterLengths_[i] = parameterRow_.getLength(i + 1);
+ indicatorTotalSize_ += 2;
+
+ }
+ // @array set input (to host) array lengths of data
+ // @array if null array or 0 length array, then data length is 0
+ parameterOffsets_[i] = parameterTotalSize_;
+ parameterTotalSize_ += parameterLengths_[i];
+
+ }
+
+ if (isjvm16Synchronizer) {
+ try {
+ dummyOutputStream.write(("!!!commonExecuteBefore: Parameter "
+ + (i + 1) + " length = " + parameterLengths_[i]).getBytes()); // @C6C
+
+ } catch (Exception e) {
+ }
+ }
+ } /* for i loop */
+ if (isjvm16Synchronizer) {
+ try {
+ dummyOutputStream
+ .write(("!!!commonExecuteBefore: totalParameterLength_ = " + parameterTotalSize_)
+ .getBytes()); // @C6C
+ } catch (Exception e) {
+ }
+ }
+ changeDescriptor();
+ }
+
+ // Add the parameter information to the execute request.
+ try {
+ request.setStatementType(sqlStatement.getNativeType());
+
+ // Set the descriptor handle.
+ request.setParameterMarkerDescriptorHandle(descriptorHandle_);
+
+ // If there are any parameters, then send the parameter
+ // values with the execute data stream. Only the
+ // input parameters are included here.
+ if (parameterCount_ > 0) {
+ // In building the parameter marker data, we may discover that the //
+ // @BAA
+ // descriptor needs to be changed. If so, we will need to change the
+ // // @BAA
+ // descriptor, then rebuild the parameter marker data based on that //
+ // @BAA
+ // change. This is implemented using a do-while, but it should never
+ // // @BAA
+ // have to loop more than once, since the second time through (in a //
+ // @BAA
+ // particular execute) every thing should be great. // @BAA
+ boolean descriptorChangeNeeded = false;
+
+ do {
+ descriptorChangeNeeded = false; // Reset our flag every time through
+ // the loop.
+
+ // Allocate the space for the Extended Parameter Marker Data @G9A
+ // This is the amount of space for all of the rows' data and
+ // indicators @G9A
+ DBData parameterMarkerData;
+ int rowCount = batchExecute_ ? batchParameterRows_.size() : 1;
+
+ //
+ // Determine if compression on insert is to be used.
+ // @K3A
+ boolean useVariableFieldInsertCompression = false;
+ if (batchExecute_) {
+ if (rowCount > 0 && useVariableFieldInsertCompression()) {
+ useVariableFieldInsertCompression = true;
+ }
+ }
+
+ // @array create new x382f here if parms contain array
+ if (parameterRow_.containsArray_) // @array
+ { // @array
+ parameterMarkerData = new DBVariableData(parameterInputCount_, 2,
+ headerTotalSize_, indicatorTotalSize_, parameterTotalSize_); // @array
+ // x382f
+ // codepoint
+ // //@array4
+ // Dont use variableFieldInsertCompression with arrays @K3A
+ if (useVariableFieldInsertCompression) {
+ useVariableFieldInsertCompression = false;
+ }
+ } // @array
+ else if (connection_.useExtendedFormats()) {
+ parameterMarkerData = new DBExtendedData(rowCount,
+ parameterCount_, 2, parameterTotalSize_);
+ } else {
+ parameterMarkerData = new DBOriginalData(rowCount,
+ parameterCount_, 2, parameterTotalSize_);
+ // If extended formats are not used, then
+ // variableFieldInsertCompression cannot be used @K3A
+ if (useVariableFieldInsertCompression) {
+ useVariableFieldInsertCompression = false;
+ }
+ }
+
+ int parameterOffset = 0; /*Track the offset to the parameter within the row @K3A*/
+ int rowDataOffset = 0; /*Track the offset to the start of the row @K3A*/
+ for (int rowLoop = 0; rowLoop < rowCount; ++rowLoop) // @G9a
+ {
+ Object[] parameters = null; // @G9A
+ if (batchExecute_) // @G9A
+ {
+ // @G9A
+ // @CRS - Don't need to synch around this because we have been
+ // called
+ // by executeBatch() which is already inside the synch block.
+ parameters = (Object[]) batchParameterRows_.get(rowLoop); // @G9A
+ } // @G9A
+
+ // If this is the first of multiple rows. Set the Parameter Marker
+ // @G9A
+ // Data code point and consistency token only once @G9A
+ if (rowLoop == 0) // @G9A
+ {
+
+ // The call to setParameterMarkerData sets the calculated length of the parameter marker data
+ // in the request. This value is stored in request.lockedLength_ and
+ // request.currentOffset_ has been updated.
+ if (useVariableFieldInsertCompression) { /*@K3A*/
+ // For variable field insert compression, we need to record where the
+ // parameter length was stored so it can be updated.
+ // This is done after processing the parameters by calling request.updateLength
+ requestLengthOffset = request.setParameterMarkerDataReserve(parameterMarkerData);
+ ((DBExtendedData) parameterMarkerData)
+ .setParameterMarkerInputCompression(true);
+ } else {
+ request.setParameterMarkerData(parameterMarkerData);
+ }
+
+ parameterMarkerData.setConsistencyToken(1); // @G9M
+ } // @G9A
+
+ /* calculate the rowDataOffset. This calculation is different
+ * the first time through the look. The calculation is different
+ * if variableFieldInsertCompression is used.
+ */
+ if (rowLoop == 0) {
+ if (useVariableFieldInsertCompression) {
+ // Save the initialRawOffset so that the size can
+ // be calculated after all the parameter has been added
+ initialRawOffset = ((DBExtendedData)parameterMarkerData).getRawOffset();
+ }
+ // Get the initial row offset.
+ rowDataOffset = parameterMarkerData.getRowDataOffset(rowLoop); // @G9C
+
+ } else {
+ if (useVariableFieldInsertCompression) {
+ // calculate the row offset base on the parameters last added
+ rowDataOffset += parameterOffset;
+ } else {
+ rowDataOffset = parameterMarkerData.getRowDataOffset(rowLoop); // @G9C
+ }
+ }
+ parameterOffset = 0;
+ for (int i = 0; i < parameterCount_; ++i) {
+ // @G1 -- zero out the comm buffer if the parameter marker is
+ // null.
+ // If the buffer is not zero'ed out old data will be sent to
+ // the system possibily messing up a future request.
+ if ((batchExecute_ &&
+ (parameters != null) &&
+
+ (parameters[i] == null || parameters[i] instanceof Byte))
+ || // @G9A //@EIC
+ (!batchExecute_ && (parameterNulls_[i]
+ || parameterDefaults_[i] || parameterUnassigned_[i]))) // @B9C
+ // @G9C
+ // //@EIC
+ {
+ short indicatorValue = INDICATOR_NULL; // @EIA
+ if (batchExecute_ && (parameters != null)) // @EIA
+ { // @EIA
+ if (parameters[i] == null) // @EIA
+ indicatorValue = INDICATOR_NULL; // @EIA
+ else if (((Byte) parameters[i]).byteValue() == 1) // @EIA
+ indicatorValue = INDICATOR_DEFAULT; // @EIA
+ else if (((Byte) parameters[i]).byteValue() == 2) // @EIA
+ indicatorValue = INDICATOR_UNASSIGNED; // @EIA
+ } // @EIA
+ else // @EIA
+ { // @EIA
+ if (parameterNulls_[i]) // @EIA
+ indicatorValue = INDICATOR_NULL; // @EIA
+ else if (parameterDefaults_[i]) // @EIA
+ indicatorValue = INDICATOR_DEFAULT; // @EIA
+ else if (parameterUnassigned_[i]) // @EIA
+ indicatorValue = INDICATOR_UNASSIGNED; // @EIA
+ } // @EIA
+
+ SQLData sqlData = parameterRow_.getSQLType(i + 1); // @array
+
+ // @array Don't set indicator here for null array, since
+ // setting header below will set it
+ if (sqlData.getType() != java.sql.Types.ARRAY)
+ parameterMarkerData
+ .setIndicator(rowLoop, i, indicatorValue); // @G1a @G9C
+ // @EIC
+
+ // @array only zero-out data on non-arrays
+ // If the whole array is null, then we do not even include
+ // blank data in the stream since a null array has space for
+ // values (just 0X9911ffff in header of 0X382f)
+ if (sqlData.getType() != java.sql.Types.ARRAY) // @array
+ {
+ byte[] parameterData = parameterMarkerData.getRawBytes(); // @G1a
+
+ if (useVariableFieldInsertCompression) { /*@K3A*/
+ if (sqlData instanceof SQLVariableCompressible) {
+ // If a variable compressible field, initialize the
+ // size to zero for null data
+ parameterData[rowDataOffset + parameterOffset]=0;
+ parameterOffset++;
+ parameterData[rowDataOffset + parameterOffset]=0;
+ parameterOffset++;
+ } else {
+ // initialize the value to zero and adjust the parameter offset
+ int parameterDataOffset = rowDataOffset + parameterOffset;
+ int parameterDataLength = parameterLengths_[i]
+ + parameterDataOffset;
+ for (int z = parameterDataOffset;
+ z < parameterDataLength;
+ parameterData[z++] = 0x00) {
+ }
+ parameterOffset += parameterLengths_[i];
+ }
+ } else {
+
+
+ int parameterDataOffset = rowDataOffset
+ + parameterOffsets_[i]; // @G1a
+ int parameterDataLength = parameterLengths_[i]
+ + parameterDataOffset;
+ for (int z = parameterDataOffset; z < parameterDataLength; parameterData[z++] = 0x00) {
+
+ }
+ }
+ }
+
+ // @array If the row contains an array, then we must also set
+ // the columnInfo in stream header
+ if (parameterRow_.containsArray_
+ && parameterRow_.isInput(i + 1)) // @array //@array4
+ { // @array
+ int arrayLen = -1; // @array
+ int elementType = -1; // @array
+ int size = -1; // @array
+ if (sqlData.getType() == java.sql.Types.ARRAY) // @array
+ { // @array
+ arrayLen = ((SQLArray) sqlData).getArrayCount(); // @array
+ elementType = ((SQLArray) sqlData).getElementNativeType(); // @array
+ size = parameterRow_.getArrayDataLength(i + 1); // @array@G2C
+ } // @array
+ ((DBVariableData) parameterMarkerData).setHeaderColumnInfo(
+ i, (short) sqlData.getNativeType(),
+ (short) indicatorValue, (short) elementType, size,
+ (short) arrayLen); // @array
+ } // @array
+ } else { /* Data is not null */
+ SQLData sqlData = parameterRow_.getSQLType(i + 1); // @array
+ if (!parameterRow_.containsArray_
+ || parameterRow_.isInput(i + 1)) // @array4
+ {
+ // Setting array null value here for elements inside of
+ // array)
+ if (sqlData.getType() == java.sql.Types.ARRAY) // @array
+ { // @array
+ // iterate through elements and set null indicators. Array
+ // as a whole null is not set here (see above)
+ for (int e = 0; e < ((SQLArray) sqlData).getArrayCount(); e++) // @array
+ { // @array
+ if (((SQLArray) sqlData).isElementNull(e)) // @array
+ parameterMarkerData.setIndicator(0, i, -1); // @array
+ else
+ // @array
+ parameterMarkerData.setIndicator(0, i, 0); // @array
+ } // @array
+ } else {
+ parameterMarkerData.setIndicator(rowLoop, i, (short) 0); // @G9C
+ }
+ }
+ ConvTable ccsidConverter = connection_
+ .getConverter(parameterRow_.getCCSID(i + 1)); // @P0C
+
+ // Convert the data to bytes into the parameter marker data.
+ // // @BAA
+ // If there is an exception here, it means that there were //
+ // @BAA
+ // not enough bytes in the descriptor for the conversion. //
+ // @BAA
+ // If so, we get the correct length via getPrecision() // @BAA
+ // (assume the SQLData implementation has updated its own //
+ // @BAA
+ // precision as needed). // @BAA
+ int correctLength = -1; // @BAA
+
+ // Put each row's values back into the SQL data type for their
+ // respective columns.
+ if (batchExecute_ && parameters != null) {
+ // @CRS If the type is a locator, we pass -1 here so the
+ // locator will know
+ // not to reset its length, because the length wasn't saved
+ // with the
+ // parameter when addBatch() was called, but since we reuse
+ // the SQLData
+ // objects, it's still saved off inside the SQLLocator.
+ setValue(i + 1, parameters[i], null, -1);
+ }
+
+ // SQLData sqlData = parameterRow_.getSQLType(i+1); // @BAC
+ // @P0C @G9C //@array move above
+
+ try {
+ if (!parameterRow_.containsArray_
+ || parameterRow_.isInput(i + 1)) // @array4 (if array
+ // then only send input
+ // parm data)
+ {
+ // @CRS - This is the only place convertToRawBytes is ever
+ // called.
+ // @K3A compress the data if needed using variable field compression
+ if (useVariableFieldInsertCompression) {
+ if (sqlData instanceof SQLVariableCompressible) {
+ // @K3A write the compressed bytes for the field.
+ int written = ((SQLVariableCompressible) sqlData)
+ .convertToCompressedBytes(
+ parameterMarkerData.getRawBytes(),
+ rowDataOffset + parameterOffset,
+ ccsidConverter);
+ parameterOffset += written;
+ } else {
+ sqlData.convertToRawBytes(
+ parameterMarkerData.getRawBytes(), rowDataOffset
+ + parameterOffset, ccsidConverter);
+ // Increment by the length of the parameter
+ parameterOffset += parameterLengths_[i];
+ }
+ } else {
+ sqlData.convertToRawBytes(
+ parameterMarkerData.getRawBytes(), rowDataOffset
+ + parameterOffsets_[i], ccsidConverter);
+ }
+
+ if (ConvTable.isMixedCCSID(ccsidConverter.getCcsid())) // @trnc
+ // this
+ // is
+ // not caught at
+ // setX() time
+ // @H2C
+ testDataTruncation(i + 1, sqlData); // @trnc
+ }
+
+ // @array If the row contains an array, then we must also
+ // set the columnInfo in stream header
+ if (parameterRow_.containsArray_
+ && parameterRow_.isInput(i + 1)) // @array //@array4
+ { // @array
+ // Set the stream header info for each column in addition
+ // to data in rawbytes above.
+ int arrayLen = -1; // @array
+ int elementType = -1; // @array
+ int size; // @array
+ if (sqlData.getType() == java.sql.Types.ARRAY) // @array
+ { // @array
+ size = parameterRow_.getArrayDataLength(i + 1); /* @G2A */
+ arrayLen = ((SQLArray) sqlData).getArrayCount(); // @array
+ elementType = ((SQLArray) sqlData)
+ .getElementNativeType(); // @array
+ } else { // @array
+ size = parameterRow_.getLength(i + 1);
+ }
+ ((DBVariableData) parameterMarkerData)
+ .setHeaderColumnInfo(i,
+ (short) sqlData.getNativeType(), (short) 0,
+ (short) elementType, size, (short) arrayLen); // @array
+ } // @array
+
+ } catch (SQLException e) {
+ if (e.getSQLState().trim().equals("HY000")) // AN INTERNAL
+ // DRIVER ERROR
+ {
+ // Check error to see if it was thrown from another error
+ if (parameterRow_.containsArray_) // @array always use
+ // prepare/describe
+ // lengths
+ throw e; // @array
+ if (e.getMessage().indexOf("Change Descriptor") != -1) {
+ correctLength = sqlData.getPrecision(); // @BAA
+ } else
+ throw e;
+ } else
+ throw e;
+ } // @BAA
+
+ // If the length needed is larger than what was allocated in
+ // // @BAA
+ // the descriptor, then change the descriptor, and start //
+ // @BAA
+ // again. // @BAA
+ if (correctLength >= 0) {
+ descriptorChangeNeeded = true; // @BAA
+ parameterLengths_[i] = correctLength; // @BAA
+ parameterTotalSize_ = parameterOffsets_[i] + correctLength; // @BAA
+ if ((i + 1) < parameterCount_) {
+ for (int j = i + 1; j < parameterCount_; ++j) {
+ parameterOffsets_[j] = parameterTotalSize_; // @BAA
+ parameterTotalSize_ += parameterLengths_[j]; // @BAA
+ } // @BAA
+ } // @BAA
+ } // @BAA
+ }
+ }
+ if (descriptorChangeNeeded)
+ changeDescriptor();
+ } /* for loop */
+
+ // For variable field compression update the length of the parameter block
+ // by calculating the parameters length. @K3A
+ if (useVariableFieldInsertCompression) {
+ rowDataOffset += parameterOffset;
+ int parametersLength = rowDataOffset - initialRawOffset;
+
+ request.updateLength(requestLengthOffset, parametersLength);
+ }
+ } while (descriptorChangeNeeded);
+ request.setParameterMarkerBlockIndicator(0);
+ }
+
+ // If we are expecting output parameters
+ // to be returned, then ask for them as result data.
+ if (outputParametersExpected_)
+ request
+ .addOperationResultBitmap(DBSQLRequestDS.ORS_BITMAP_RESULT_DATA);
+ } catch (DBDataStreamException e) {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ }
+ }
+ }
+
+ /**
+ * Should variable field compression be used for these parameters.
+ * We will compress if at least 1/3 of the row is VARIABLE data.
+ *
+ * @throws SQLException
+ */
+ /*@K3A*/
+ private boolean useVariableFieldInsertCompression() throws SQLException {
+ if (useVariableFieldInsertCompression_) {
+ int totalSize = 0;
+ int compressibleSize = 0;
+ for (int parameterNumber = 0; parameterNumber < parameterCount_; parameterNumber++) {
+ int parameterSize = parameterRow_.getLength(parameterNumber+1);
+ SQLData sqlData = parameterRow_.getSQLType(parameterNumber + 1);
+ if (sqlData instanceof SQLVariableCompressible) {
+ compressibleSize += parameterSize;
+ }
+ totalSize += parameterSize;
+ }
+ if (compressibleSize > (totalSize / 3)) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Performs common operations needed after a prepare.
+ *
+ * @param sqlStatement
+ * The SQL statement.
+ * @param reply
+ * The prepare reply.
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ void commonPrepareAfter(JDSQLStatement sqlStatement, DBReplyRequestedDS reply)
+ throws SQLException {
+ super.commonPrepareAfter(sqlStatement, reply);
+
+ if (prepared_) {
+ parameterRow_ = new JDServerRow(connection_, id_,
+ reply.getParameterMarkerFormat(), settings_);
+
+ }
+ }
+
+ /**
+ * Performs common operations needed before a prepare.
+ *
+ * @param sqlStatement
+ * The SQL statement.
+ * @param request
+ * The prepare request.
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ void commonPrepareBefore(JDSQLStatement sqlStatement, DBSQLRequestDS request)
+ throws SQLException {
+ super.commonPrepareBefore(sqlStatement, request);
+
+ if (prepared_) {
+ request
+ .addOperationResultBitmap(DBSQLRequestDS.ORS_BITMAP_PARAMETER_MARKER_FORMAT);
+ }
+ }
+
+ /**
+ * Performs common operations in leiu of a prepare.
+ *
+ * @param sqlStatement
+ * The SQL statement.
+ * @param statementIndex
+ * The cached statement index.
+ * @exception SQLException
+ * If an error occurs.
+ **/
+ void commonPrepareBypass(JDSQLStatement sqlStatement, int statementIndex)
+ throws SQLException {
+ super.commonPrepareBypass(sqlStatement, statementIndex);
+
+ if (prepared_) {
+ parameterRow_ = new JDServerRow(connection_, id_,
+ packageManager_.getCachedParameterMarkerFormat(statementIndex),
+ settings_);
+ }
+ }
+
+ /**
+ * Runs an SQL statement that may return multiple result sets. This closes the
+ * current result set and clears warnings before executing the SQL statement
+ * again.
+ *
+ *
+ * Under some situations, a single SQL statement may return multiple result
+ * sets, an update count, or both. This might occur either when executing a
+ * stored procedure that returns multiple result sets or when dynamically
+ * executing an unknown SQL string.
+ *
+ *
+ * Use Statement.getMoreResults(), Statement.getResultSet(), and
+ * Statement.getUpdateCount() to navigate through multiple result sets, an
+ * update count, or both.
+ *
+ * @return true if a result set was returned; false if an update count was
+ * returned or nothing was returned.
+ * @exception SQLException
+ * If the statement is not open, the query timeout limit is
+ * exceeded, or an error occurs.
+ **/
+ public boolean execute() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (!prepared_) {
+ resultRow_ = commonPrepare(sqlStatement_);
+ prepared_ = true;
+ }
+
+ commonExecute(sqlStatement_, resultRow_);
+ executed_ = true;
+
+ return (resultSet_ != null);
+ }
+ }
+
+ /**
+ * Runs an SQL statement that may return multiple result sets. This closes the
+ * current result set and clears warnings before executing a new SQL
+ * statement.
+ *
+ *
+ * Do not use this form of execute() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement.
+ * @return true if a result set was returned, false if an update count was
+ * returned or nothing was returned.
+ * @exception SQLException
+ * This exception is always thrown.
+ **/
+ public boolean execute(String sql) throws SQLException {
+ /*
+ * @B1D // Call the super class execute() method. Note that this // results
+ * in the prepare of a different statement, so the // we must mark ours and
+ * not prepared. prepared_ = false;
+ *
+ * return super.execute (sql);
+ */
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @B1A
+ return false; // @B1A
+ }
+
+ // @GAA
+ /**
+ * Runs an SQL statement that may return multiple result sets and makes any
+ * auto-generated keys available for retrieval using
+ * Statement.getGeneratedKeys(). This closes the current result set and clears
+ * warnings before executing the new SQL statement.
+ *
+ *
+ * Do not use this form of execute() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement.
+ * @param autoGeneratedKeys
+ * Indicates whether auto-generated keys should be made available for
+ * retrieval. Valid values are Statement.RETURN_GENERATED_KEYS and
+ * Statement.NO_GENERATED_KEYS.
+ * @return true if a result set was returned, false if an update count was
+ * returned or nothing was returned.
+ * @exception SQLException
+ * This exception is always thrown.
+ * @since Modification 5
+ **/
+ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ return false; // @B1A
+ }
+
+ /**
+ * Runs the batch of SQL statements. Batch updates can be used to submit a set
+ * of SQL statements together as a single unit. The SQL statements are run in
+ * the order in which they were added to the batch. The batch is cleared after
+ * the SQL statements are run. In addition, this closes the current result set
+ * and clears warnings before executing the new SQL statement.
+ *
+ *
+ * When batch updates are run, autocommit should usually be turned off. This
+ * allows the caller to decide whether or not to commit the transaction in the
+ * event that an error occurs and some of the SQL statements in a batch fail
+ * to run.
+ *
+ * @return An array of row counts for the SQL statements that are run. The
+ * array contains one element for each statement in the batch of SQL
+ * statements. The array is ordered according to the order in which
+ * the SQL statements were added to the batch.
+ * @exception SQLException
+ * If the statement is not open, an SQL statement contains a
+ * syntax error, the query timeout limit is exceeded, an SQL
+ * statement returns a result set, or an error occurs.
+ **/
+ public int[] executeBatch() throws SQLException {
+ synchronized (internalLock_) { // @F1A
+ checkOpen();
+
+ if (batch_ == null || batch_.size() == 0)
+ return new int[0];
+
+ batchParameterRows_ = new Vector();
+
+ int batchSize = batch_.size();
+ int[] updateCounts = new int[batchSize];
+
+ int numSuccessful = 0; // Number of successfully executed statements in
+ // the batch.
+
+ boolean canBatch = true;
+ // boolean notInsert = false; //@blksql
+
+ try {
+ // Only INSERTs can be batched, UPDATE statements must still be done one
+ // at a time.
+ // if(!(sqlStatement_.isInsert_)) //@blksql
+ // {
+ // canBatch = false;
+ // notInsert = true;
+ // }
+
+ if (!(sqlStatement_.canBatch())) {
+ canBatch = false;
+ }
+
+ // For sure we have a locator, so we can't batch it,
+ // because the host server only reserves space for one locator handle.
+ if (containsLocator_ == LOCATOR_FOUND) {
+ canBatch = false;
+ }
+
+ // Set the batch execute flag so common execute knows to use the list
+ // @G9A
+ // of parameter rows. @G9A
+ batchExecute_ = true; // @G9A
+ rowsInserted_ = 0; // @G9A
+
+ // Prepare the statement if it is not already done.
+ if (!prepared_) {
+ // @H7 Native type should ONLY be BLOCK_INSERT if the statement is of
+ // type
+ // @H7 "INSERT INTO MYTABLE ? ROWS VALUES (?,?)" with a ROWS VALUES
+ // clause,
+ // @H7 not just if we are going to send the values as a batch to the
+ // system.
+ // @H7 We determine whether the statement is of that form in
+ // @H7 JDSQLStatement.java, not here.
+ // @H7D sqlStatement_.setNativeType(JDSQLStatement.TYPE_BLOCK_INSERT);
+ // // @G9A
+ resultRow_ = commonPrepare(sqlStatement_);
+ prepared_ = true;
+ // See if the prepare returned a ResultSet. If so, error out now to
+ // avoid
+ // opening a cursor. Note some stored procedures won't return a
+ // ResultSet
+ // until the execute, so we check in both places.
+ if (resultSet_ != null) {
+ closeResultSet(JDCursor.REUSE_YES);
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ }
+
+ // Execute.
+ if (canBatch) {
+ int maximumBlockedInputRows = connection_
+ .getMaximumBlockedInputRows();
+ Enumeration list = batch_.elements();
+ int count = 0; // @K1A Added support for allowing more than 32000 SQL
+ // Statements to be batched and run
+ int totalUpdateCount = 0; /* @A4A */
+ while (list.hasMoreElements()) {
+ batchParameterRows_.add(list.nextElement());
+ count++; // @K1A
+ if (count == maximumBlockedInputRows && list.hasMoreElements())// @K1A
+ // Checks
+ // if
+ // 32000
+ // statements
+ // have
+ // been
+ // added
+ // to
+ // the
+ // batch,
+ // if
+ // so
+ // execute
+ // the
+ // first
+ // 32000,
+ // then
+ // continue
+ // processing
+ // the
+ // batch
+ { // @K1A
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this,
+ "Begin batching via server-side with "
+ + batchParameterRows_.size() + " rows."); // @K1A
+ executingBatchedStatement_ = true; /* @DAA */
+ commonExecute(sqlStatement_, resultRow_); // @K1A
+ executingBatchedStatement_ = false; /* @DAA */
+ totalUpdateCount += updateCount_; /* @A4A */
+ batchParameterRows_.clear(); // @K1A
+
+ if (resultSet_ != null) // @K1A
+ { // @K1A
+ closeResultSet(JDCursor.REUSE_YES); // @K1A
+ JDError.throwSQLException(this,
+ JDError.EXC_CURSOR_STATE_INVALID); // @K1A
+ } // @K1A
+ count = 0; // @K1A set the count for the number of statements in
+ // the batch back to zero
+ } // @K1A
+ }
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Begin batching via server-side with "
+ + batchParameterRows_.size() + " rows.");
+
+ //
+ // There is a quirk that if clearParameters is called after addBatch
+ // but before executeBatch then
+ // the commonExecute fails because it doesn't think the parameters are
+ // set.
+ // Set a flag that we are doing server side batching.
+ //
+ executingBatchedStatement_ = true; /* @DAA */
+ commonExecute(sqlStatement_, resultRow_);
+ executingBatchedStatement_ = false; /* @DAA */
+
+ totalUpdateCount += updateCount_; /* @A4A */
+ batchParameterRows_.clear();
+ if (resultSet_ != null) {
+ closeResultSet(JDCursor.REUSE_YES);
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ numSuccessful = batchSize;
+ // The host server does not currently report the update counts for
+ // each statement in
+ // the batch. We use -2 here because that is the constant for
+ // Statement.SUCCESS_NO_INFO
+ // as of JDBC 3.0 and JDK 1.4. When we change to build against JDK 1.4
+ // instead of 1.3,
+ // we can change this to use the actual constant.
+ // However, if the total number of updated rows is the same as the
+ // batch size then
+ // we can set each of the update counts to 1. @A4A
+
+ // Only set the count to one if the statement is an insert statement.
+ // The logic in JDSQLStatement only allows in insert to be batched if
+ // it is of the
+ // form insert ... VALUES(?,?,?) ... Any other form will not be
+ // batched
+ int updateCount = -2;
+ if (batchSize == totalUpdateCount && sqlStatement_.isInsert_) {
+ updateCount = 1;
+ }
+ for (int i = 0; i < batchSize; ++i) {
+ updateCounts[i] = updateCount;
+ }
+ } else {
+ // We can't really batch because we are not an INSERT, we contain a
+ // locator, or
+ // there is some other reason.
+ Enumeration list = batch_.elements();
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this,
+ "Begin batching via client-side multiple executes.");
+ while (list.hasMoreElements()) {
+ batchParameterRows_.addElement(list.nextElement());
+ // Indicate we are batching to prevent clearParameter /*@DAA*/
+ executingBatchedStatement_ = true;
+ commonExecute(sqlStatement_, resultRow_);
+ executingBatchedStatement_ = false; /* @DAA */
+ batchParameterRows_.removeAllElements();
+ if (resultSet_ != null) {
+ closeResultSet(JDCursor.REUSE_YES);
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ updateCounts[numSuccessful++] = rowsInserted_;
+ }
+ }
+ executed_ = true;
+ } catch (SQLException e) {
+ // The specification says that if we get an error,
+ // then the size of the update counts array should
+ // reflect the number of statements that were
+ // executed without error.
+ int[] counts = null;
+ if (canBatch) {
+ // @CRS - We must be an INSERT...?? But we don't know which statement
+ // in the batch
+ // caused the exception, so all we can do is return an array of size 1
+ // with the
+ // number of rows inserted/updated according to the host server.
+ // After some investigation, the above is not true. See below: //@550
+ // If autocommit is on and we are running under *NONE, then
+ // rowsInserted_ contains the number //@550
+ // of inserts that executed successfully before the error.
+ // rowsInserted_ is set from the //@550
+ // the value in SQLERRD3. If autocommit is running under an isolation
+ // level other than *NONE, //@550
+ // or autocommit is off, no rows are committed. Thus rowsInserted_
+ // will be zero. //@550
+ // Since we don't have any update counts for each statement, use
+ // Statement.SUCCESS_NO_INFO //@550
+ // @550D counts = new int[] { rowsInserted_};
+ counts = new int[rowsInserted_]; // @550 batch update support
+ for (int i = 0; i < counts.length; i++)
+ // @550
+ counts[i] = Statement.SUCCESS_NO_INFO; // @550
+
+ } else {
+ // @CRS - Since we haven't really been batching, we've been keeping
+ // track of everything
+ // per execute, so we can return more useful information.
+ counts = new int[numSuccessful];
+ System.arraycopy(updateCounts, 0, counts, 0, numSuccessful);
+ }
+ BatchUpdateException batchUpdateException = new BatchUpdateException(
+ e.getMessage(), e.getSQLState(), e.getErrorCode(), counts);
+ // Attempt to set the cause, ignoring any failures (i.e. in Pre JDK 1.4)
+ // /*@DAA*/
+ try {
+ batchUpdateException.initCause(e);
+ } catch (java.lang.NoSuchMethodError e2) {
+ }
+
+ throw batchUpdateException;
+ } finally {
+ batch_.removeAllElements();
+ batchExecute_ = false; // @K1A
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Done batching.");
+ }
+ return updateCounts;
+ }
+ }
+
+ /**
+ * Runs the SQL statement that returns a single result set. This closes the
+ * current result set and clears warnings before executing the SQL statement
+ * again.
+ *
+ * @return The result set that contains the data produced by the query.
+ * @exception SQLException
+ * If the statement is not open, no result set is returned by the
+ * database, the query timeout limit is exceeded, an input
+ * parameter has not been set, or an error occurs.
+ **/
+ public ResultSet executeQuery() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (!prepared_) {
+ resultRow_ = commonPrepare(sqlStatement_);
+ prepared_ = true;
+ }
+
+ commonExecute(sqlStatement_, resultRow_);
+ executed_ = true;
+
+ if (resultSet_ == null && ((behaviorOverride_ & 1) == 0)) {
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+ return resultSet_;
+ }
+ }
+
+ /**
+ * Runs an SQL statement that returns a single result set. This closes the
+ * current result set and clears warnings before executing a new SQL
+ * statement.
+ *
+ *
+ * Do not use this form of executeQuery() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement.
+ * @return The result set that contains the data produced by the query.
+ * @exception SQLException
+ * This exception is always thrown.
+ **/
+ public ResultSet executeQuery(String sql) throws SQLException {
+ /*
+ * @B1D // Call the super class execute() method. Note that this // results
+ * in the prepare of a different statement, so the // we must mark ours and
+ * not prepared. prepared_ = false;
+ *
+ * return super.executeQuery (sql);
+ */
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @B1A
+ return null; // @B1A
+ }
+
+ /**
+ * Runs an SQL INSERT, UPDATE, or DELETE statement, or any SQL statement that
+ * does not return a result set. This closes the current result set and clears
+ * warnings before executing the SQL statement again.
+ *
+ * @return Either the row count for INSERT, UPDATE, or DELETE, or 0 for SQL
+ * statements that return nothing.
+ * @exception SQLException
+ * If the statement is not open, the query timeout limit is
+ * exceeded, the statement returns a result set, an input
+ * parameter has not been set, or an error occurs.
+ **/
+ public int executeUpdate() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Prepare and execute. Check for a result set in both
+ // places. It is best to catch it after the prepare (so
+ // we don't open a cursor), but with some stored procedures,
+ // we can't catch it until the execute.
+
+ // Prepare the statement if it is not already done.
+ if (!prepared_) {
+ resultRow_ = commonPrepare(sqlStatement_);
+ prepared_ = true;
+ if (resultRow_ != null)
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+ // Execute.
+ commonExecute(sqlStatement_, resultRow_);
+ executed_ = true;
+
+ if (resultSet_ != null) {
+ closeResultSet(JDCursor.REUSE_YES);
+ JDError.throwSQLException(this, JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+ return updateCount_;
+ }
+ }
+
+ /**
+ * Runs an SQL INSERT, UPDATE, or DELETE statement, or any SQL statement that
+ * does not return a result set. This closes the current result set and clears
+ * warnings before executing a new SQL statement.
+ *
+ *
+ * Do not use this form of executeUpdate() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement.
+ * @return Either the row count for INSERT, UPDATE, or DELETE, or 0 for SQL
+ * statements that return nothing.
+ * @exception SQLException
+ * This exception is always thrown.
+ **/
+ public int executeUpdate(String sql) throws SQLException {
+ /*
+ * @B1D // Call the super class execute() method. Note that this // results
+ * in the prepare of a different statement, so the // we must mark ours and
+ * not prepared. prepared_ = false;
+ *
+ * return super.executeUpdate (sql);
+ */
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE); // @B1A
+ return 0; // @B1A
+ }
+
+ // @GAA
+ /**
+ * Runs an SQL INSERT, UPDATE, or DELETE statement, or any SQL statement that
+ * does not return a result set and makes any auto-generated keys available
+ * for retrieval using Statement.getGeneratedKeys(). This closes the current
+ * result set and clears warnings before executing the new SQL statement.
+ *
+ *
+ * Do not use this form of executeUpdate() on a prepared statement.
+ *
+ * @param sql
+ * The SQL statement.
+ * @return Either the row count for INSERT, UPDATE, or DELETE, or 0 for SQL
+ * statements that return nothing.
+ * @exception SQLException
+ * This exception is always thrown.
+ * @since Modification 5
+ **/
+ public int executeUpdate(String sql, int autoGeneratedKeys)
+ throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ return 0;
+ }
+
+ // JDBC 2.0
+ /**
+ * Returns the ResultSetMetaData object that describes the result set's
+ * columns. Null is returned if the statement does not return a result set. In
+ * the following example rsmd is null since the statement does not return a
+ * result set.
+ *
+ *
+ * Note that the number of bytes in a Unicode stream can be computed as 2
+ * multiplied by the number of characters plus 2 bytes for the byte-order
+ * mark. If an uneven number of bytes is specified, then Java will convert
+ * this to an empty String.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 Unicode characters, or
+ * an error occurs while reading the input stream
+ * @deprecated Use setCharacterStream(int, Reader, int) instead.
+ * @see #setCharacterStream
+ **/
+ public void setUnicodeStream(int parameterIndex, InputStream parameterValue,
+ int length) throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setUnicodeStream()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length); // @H1A
+ } // @H1A
+
+ // Validate the length parameter
+ if (length < 0)
+ JDError.throwSQLException(this, JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (parameterValue != null) {
+
+ try {
+ // If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (sqlType == SQLData.CLOB_LOCATOR
+ || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR || // @pdc jdbc40
+/* ifdef JDBC40 */
+ sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
+/* endif */
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ sqlData.set(new ConvTableReader(parameterValue, 13488, 0,
+ LOB_BLOCK_SIZE), null, length / 2); // @J0M hacked this to use
+ // the scale parm for the
+ // length
+ } else {
+ sqlData.set(JDUtilities.readerToString(new ConvTableReader(
+ parameterValue, 13488, 0, LOB_BLOCK_SIZE), length / 2), null,
+ -1);
+ }
+ } catch (UnsupportedEncodingException uee) {
+ /* do nothing */
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (parameterValue == null);
+ parameterDefaults_[parameterIndex - 1] = false; // @EIA
+ parameterUnassigned_[parameterIndex - 1] = false; // @EIA
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+
+ // @J0D setValue (parameterIndex,
+ // @J0D (parameterValue == null) ? null : JDUtilities.streamToString
+ // (parameterValue, length, "UnicodeBig"), // @B2C @B3C @H2C @H3C
+ // @J0D null, -1); //@P0C
+ }
+
+ // @G4A JDBC 3.0
+ /**
+ * Sets an input parameter to a URL value. The driver converts this to an SQL
+ * DATALINK value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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.
+ * @since Modification 5
+ **/
+ public void setURL(int parameterIndex, URL parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setURL()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ /**
+ * Sets an input parameter value for the specified index, and performs all
+ * appropriate validation.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null if the value is SQL NULL.
+ * @param calendar
+ * The calendar, or null if not applicable.
+ * @param scale
+ * The scale, or -1 if not applicable.
+ * @exception SQLException
+ * If the statement is not open, the index is not valid or the
+ * parameter is not an input parameter.
+ **/
+ void setValue(int parameterIndex, Object parameterValue, Calendar calendar,
+ int scale) throws SQLException {
+
+ synchronized (internalLock_) { // @F1A
+ checkOpen();
+
+ // Check if the parameter index refers to the return value parameter. @F2A
+ // This is an OUT parameter, so sets are not allowed. If its not @F2A
+ // parameter index 1, then decrement the parameter index, since we @F2A
+ // are "faking" the return value parameter. @F2A
+ if (useReturnValueParameter_) { // @F2A
+ if (parameterIndex == 1) // @F2A
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);// @F2A
+ else
+ // @F2A
+ --parameterIndex; // @F2A
+ }
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_)) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex); // @P0C
+ if (parameterValue != null) { // @B6C
+ // If the data is a locator, then set its handle. @B6A
+ int sqlType = sqlData.getSQLType();
+ if((sqlType == SQLData.CLOB_LOCATOR ||
+ sqlType == SQLData.BLOB_LOCATOR ||
+ sqlType == SQLData.DBCLOB_LOCATOR || //@pdc jdbc40
+/* ifdef JDBC40 */
+ sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
+/* endif */
+ sqlType == SQLData.XML_LOCATOR)) // @xml3
+ { // @B6A
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData; // @B6A
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex)); // @B6A
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ } // @B6A
+
+ sqlData.set(parameterValue, calendar, scale);
+ if (dataTruncation_ || !sqlData.isText()) {
+ testDataTruncation(parameterIndex, sqlData); // @B5C @G5move
+ }
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database. // @B6A
+ parameterNulls_[parameterIndex - 1] = (parameterValue == null);
+ parameterDefaults_[parameterIndex - 1] = false; // @EIA
+ parameterUnassigned_[parameterIndex - 1] = false; // @EIA
+ parameterSet_[parameterIndex - 1] = true;
+ }
+ }
+
+ // @EIA new method
+ /**
+ * Sets an input parameter value for the specified index, and performs all
+ * appropriate validation when the value is one of the valid Extended
+ * Indicator values: default or unassigned.
+ *
+ * Note: this is the same type of method as setValue() above, but we have no
+ * way to pass in the special values without hacking some sort of flag string
+ * for the value, and that seemed to be a messy and slow way to do this.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter 1="default" or 2="unassigned".
+ * @exception SQLException
+ * If the statement is not open, the index is not valid or the
+ * parameter is not an input parameter.
+ **/
+ void setValueExtendedIndicator(int parameterIndex, int parameterValue)
+ throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_)) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ parameterNulls_[parameterIndex - 1] = false;
+ parameterDefaults_[parameterIndex - 1] = parameterValue == 1 ? true
+ : false;
+ parameterUnassigned_[parameterIndex - 1] = parameterValue == 2 ? true
+ : false;
+ parameterSet_[parameterIndex - 1] = true;
+ }
+ }
+
+ /**
+ * Tests if a DataTruncation occurred on the write of a piece of data and
+ * throws a DataTruncation exception if so. The data truncation flag is also
+ * taken into consideration for string data. The rules are: 1) If updating
+ * database with numeric data and data truncated, throw exception 2) If
+ * numeric data is part of a query and data truncated, post warning 3) If
+ * string data and suppress truncation, return 4) If updating database with
+ * string data and check truncation and data truncated, throw exception 5) If
+ * string data is part of a query and check truncation and data truncated,
+ * post warning
+ *
+ * @param index
+ * The index (1-based).
+ * @param data
+ * The data that was written or null for SQL NULL.
+ **/
+ private void testDataTruncation(int parameterIndex, SQLData data)
+ throws SQLException // @trunc
+ {
+ if (data != null && (dataTruncation_ || !data.isText())) {
+ // The SQLData object determined if data was truncated as part of the
+ // setValue() processing.
+ int truncated = data.getTruncated();
+ if (truncated > 0) {
+ int actualSize = data.getActualSize();
+ // boolean isRead = sqlStatement_.isSelect(); //@pda jdbc40 //@pdc same
+ // as native (only select is read) //@trunc //@pdc match native
+ DataTruncation dt = new DataTruncation(parameterIndex, true, false,
+ actualSize + truncated, actualSize); // @pdc jdbc40 //@trunc //@pdc
+ // match native
+
+ // if 610 and number data type, then throw DataTruncation
+ // if text, then use old code path and post/throw DataTruncation
+ if ((connection_.getVRM() >= JDUtilities.vrm610)
+ && (data.isText() == false)) // @trunc2
+ { // @trunc2
+ throw dt; // @trunc2
+ } // @trunc2
+ else if ((sqlStatement_ != null) && (sqlStatement_.isSelect())
+ && (!sqlStatement_.isSelectFromInsert())) // @trunc2 //@selins1
+ {
+ postWarning(dt);
+ } else {
+ throw dt;
+ }
+ }
+ }
+ }
+
+ // @BBA
+ /**
+ * Checks that an input SQL type is compatible with the actual parameter type.
+ *
+ * @param sqlType
+ * The SQL type.
+ * @param parameterIndex
+ * The index (1-based).
+ * @exception SQLException
+ * If the SQL type is not compatible.
+ **/
+ void testSQLType(int sqlType, int parameterIndex) throws SQLException {
+ int parameterType = parameterRow_.getSQLType(parameterIndex).getType(); // @P0C
+
+ if (sqlType != parameterType) {
+
+ // If the only reason the types don't match is because one
+ // is a CHAR and the other is a VARCHAR, then let this
+ // slide.
+ if (((sqlType == Types.CHAR) || (sqlType == Types.VARCHAR))
+ && ((parameterType == Types.CHAR) || (parameterType == Types.VARCHAR))) {
+ // Do nothing!
+ } else {
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ }
+ }
+ }
+
+ // @GKA
+ // Returns the JDServerRow object associated with this statement.
+ JDServerRow getResultRow() {
+ return resultRow_;
+ }
+
+ // @PDA jdbc40
+ /**
+ * Sets the designated parameter to the given
+ * Note: This stream object can either be a standard Java stream object
+ * or your own subclass that implements the standard interface.
+ *
+ * @param parameterIndex
+ * @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
+ * Note: This stream object can either be a standard Java stream object
+ * or your own subclass that implements the standard interface.
+ *
+ * @param parameterIndex
+ * @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
+ * Note: This stream object can either be a standard Java stream object
+ * or your own subclass that implements the standard interface.
+ *
+ * @param parameterIndex
+ * @param reader
+ * the
+ * Note: This stream object can either be a standard Java stream object
+ * or your own subclass that implements the standard interface.
+ *
+ * @param parameterIndex
+ * @param x
+ * the Java input stream that contains the ASCII parameter value
+ * @exception SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; if a database access error occurs or this
+ * method is called on a closed
+ * Note: This stream object can either be a standard Java stream object
+ * or your own subclass that implements the standard interface.
+ *
+ * @param parameterIndex
+ * @param x
+ * the java input stream which contains the binary parameter value
+ * @exception SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; if a database access error occurs or this
+ * method is called on a closed
+ * 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
+ * Note: Consult your JDBC driver documentation to determine if it
+ * might be more efficient to use a version of
+ * 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
+ *
+ * Note: Consult your JDBC driver documentation to determine if it
+ * might be more efficient to use a version of The AS400JDBCResultSet class provides access to a table
+of data generated by a database query.
+
+ A result set maintains a cursor pointing to its current
+row of data. Initially, the cursor is positioned before the
+first row. If the result set is scrollable, use any of the
+cursor positioning methods to move the cursor within the result
+set. If the result set is not scrollable, then only use next()
+to move the cursor.
+
+ The get methods retrieve column values for the current row.
+Values can be retrieved using either the column index or the
+column name. In general, using the column index is more efficient.
+Column indexes are numbered starting with 1. Column names are
+not case sensitive. If several columns have the same name,
+then the first matching column is used.
+
+ Columns can have two names: a column name ("long name")
+and a system column name ("short name"). The get methods and
+findColumn() only support using the column name.
+
+ In each get method, the driver attempts to convert the
+underlying data to the specified Java type and returns a
+suitable Java value. If such a conversion is not appropriate,
+an SQLException is thrown.
+
+ If the result set is updatable, the update methods modify
+column values for the current row, but not in the underlying
+database. updateRow() causes all updates to the current row
+to be written to the database. Use deleteRow() to delete the
+current row in the database.
+
+ For updatable result sets, there is also an insert row,
+which is used as a staging area for the contents of a new row.
+Use moveToInsertRow() to position the cursor to the insert row.
+Once all updates to the insert row have been made, use insertRow()
+to insert the row into the database.
+
+ In the following cases, result sets are always read only
+regardless of the concurrency set in the statement:
+ In the following case, result sets are always read only
+regardless of the concurrency set in the statement if connecting
+to a system running OS/400 V4R5 or a previous release:
+ In the following case, result sets are always forward only
+regardless of the type set in the statement:
+ A result set is automatically closed by the statement that
+generated it when the statement is closed, run again, or used
+to retrieve the next result set from a sequence of multiple
+result sets.
+
+ The new JDBC 3.0 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.
+**/
+//
+// Implementation notes:
+//
+// 1. There are a few different types of result sets. For example:
+//
+// * Result sets from caller-issued selects.
+// * Result sets created and returned from DatabaseMetaData.
+// * Result sets generated on the IBM i system and mapped to
+// a different format by DatabaseMetaData.
+//
+// One solution would be to provide a different implementation
+// of java.sql.ResultSet for each of these. However, there is
+// a lot of overhead that is common to all of these. As a result,
+// I have decided to use one implementation of java.sql.ResultSet
+// and write in terms of the following interfaces, which pinpoint
+// what is truly different about the different formats:
+//
+// * JDRowCache - manages the set of rows and fetches as needed.
+// * JDRow - accesses various information about the format
+// of a row and manages the getting and setting
+// of data within a row.
+//
+// There are implementations of each of these to handle the
+// different types of result sets.
+//
+// 2. We need to know the total number of rows in the result set
+// in order to make getRow() work in all cases (e.g. after
+// a last() or absolute(-). In mod 5 the code was changed to
+// loop through the rows if we need a count. This will be
+// slow but seemed to be the best way to do it.
+// The mod 4 comment is:
+// The only way we could think of
+// to do this is to issue a SELECT COUNT(*) using the same
+// where clause as the original. However there are 2 problems:
+//
+// * There is a window of time between the original query
+// and the SELECT COUNT(*), so the value may not be
+// accurate.
+// * There is overhead in issuing another SELECT and getRow()
+// seems like it probably won't be used that often.
+//
+// Given these problems, I have decided to make getRow() not
+// work in some documented cases.
+//
+// 3. In JDBC 2.0, there are some date/time/timestamp related
+// methods that take calendar parameters and some that don't.
+// The methods that do not take calendar parameters are supposed
+// to use the default calendar (retrieved using
+// AS400Calendar.getGregorianInstance()).
+//
+// At first thought, I tried to create one static calendar
+// object to share for the entire JDBC driver, thinking that
+// this would minimize object creation and therefore improve
+// performance. However, it turns out that this shared instance
+// does not reflect TimeZone changes made after it is created,
+// so the very example given in the spec does not work. As a
+// result, we must create a new default Calendar each time.
+//
+public class AS400JDBCResultSet
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+
+implements ResultSet
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+
+ //New constants for JDBC 3.0.
+ static final int HOLDABILITY_NOT_SPECIFIED = -9999; //@G4A
+ static final int HOLD_CURSORS_OVER_COMMIT = 1; //@G4A
+ static final int CLOSE_CURSORS_AT_COMMIT = 2; //@G4A
+
+
+ // Private data.
+ private String catalog_;
+ private boolean closed_;
+ private int columnCount_;
+ private int concurrency_;
+ private Connection connection_;
+ private String correlationName_;
+ private String cursorName_;
+ private boolean dataTruncation_; // @B2A
+ private PreparedStatement deleteStatement_;
+ private int fetchDirection_;
+ private int fetchSize_;
+ private AS400JDBCStatementLock internalLock_; // @D1A @C7C
+ private int maxRows_;
+ private InputStream openInputStream_;
+ private Reader openReader_;
+ private JDRow row_;
+ private JDRowCache rowCache_;
+ private String selectTable_;
+ private SQLWarning sqlWarning_;
+ private AS400JDBCStatement statement_;
+ private int type_;
+ private boolean[] updateNulls_;
+ private boolean[] updateDefaults_; //@EIA
+ private boolean[] updateUnassigned_; //@EIA
+ private JDRow updateRow_;
+ private boolean[] updateSet_;
+ private boolean wasNull_;
+ private boolean wasDataMappingError_;
+ boolean isMetadataResultSet = false; //@mdrs
+ private DBReplyRequestedDS reply_ = null;
+ private Class byteArrayClass_ = null;
+ private SQLException savedException_; /* Saved exception from combined open/fetch @F3A*/
+ /*---------------------------------------------------------*/
+ /* */
+ /* MISCELLANEOUS METHODS. */
+ /* */
+ /*---------------------------------------------------------*/
+
+
+
+ /**
+ Constructs an AS400JDBCResultSet object.
+
+ @param statement The owning statement.
+ @param sqlStatement The SQL statement.
+ @param rowCache The row cache.
+ @param catalog The catalog.
+ @param cursorName The cursor name.
+ @param maxRows The maximum rows limit, or
+ 0 for no limit.
+ @param type The type.
+ @param concurrency The concurrency.
+ @param fetchDirection The fetch direction.
+ @param fetchSize The fetch size.
+ @param tableName The table name, if any.
+
+ @exception SQLException If an error occurs.
+ **/
+ AS400JDBCResultSet (AS400JDBCStatement statement,
+ JDSQLStatement sqlStatement,
+ JDRowCache rowCache,
+ String catalog,
+ String cursorName,
+ int maxRows,
+ int type,
+ int concurrency,
+ int fetchDirection,
+ int fetchSize)
+ throws SQLException
+ {
+ // Initialization.
+ catalog_ = catalog;
+ closed_ = false;
+ concurrency_ = concurrency;
+ connection_ = (statement != null) ? statement.getConnection () : null;
+ cursorName_ = cursorName;
+ deleteStatement_ = null;
+ fetchDirection_ = fetchDirection;
+ fetchSize_ = fetchSize;
+ internalLock_ = (statement != null) ? statement.internalLock_ : new AS400JDBCStatementLock(); // @D1A
+ maxRows_ = maxRows;
+ openInputStream_ = null;
+ openReader_ = null;
+ row_ = rowCache.getRow ();
+ rowCache_ = rowCache;
+ sqlWarning_ = null;
+ statement_ = statement;
+ type_ = type;
+ wasNull_ = false;
+ wasDataMappingError_ = false;
+
+ columnCount_ = row_.getFieldCount ();
+
+ /* @D9A Make sure that warning are provided to this result set object */
+ rowCache_.setResultSet(this);
+ rowCache_.open ();
+
+ // If no connection or SQL statement was provided,
+ // or a SELECT with multiple tables or views was
+ // specified, or the SELECT does not specify FOR UPDATE,
+ // then we cannot do updates. (@J3 In case you have
+ // paraenthesis overload, the added check in mod 5
+ // is if we are connected to a v5r1 (without PTF) or earlier
+ // system and "for update" is not specified)
+ if((connection_ == null) ||
+ (sqlStatement == null) ||
+ (((((AS400JDBCConnection) connection_).getMustSpecifyForUpdate()) && // @J3a @J31c
+ (! sqlStatement.isForUpdate()))))
+ {
+ selectTable_ = null;
+ correlationName_ = null;
+ concurrency_ = CONCUR_READ_ONLY;
+ }
+ else
+ {
+ selectTable_ = sqlStatement.getSelectTable ();
+ correlationName_ = sqlStatement.getCorrelationName ();
+ }
+
+ // Initialize the update row.
+ if(concurrency_ == CONCUR_UPDATABLE)
+ {
+ updateRow_ = new JDSimpleRow (row_, true);
+ updateSet_ = new boolean[columnCount_];
+ updateNulls_ = new boolean[columnCount_];
+ updateDefaults_ = new boolean[columnCount_]; //@EIA
+ updateUnassigned_ = new boolean[columnCount_]; //@EIA
+ for(int i = 0; i < columnCount_; ++i)
+ {
+ updateSet_[i] = false;
+ updateNulls_[i] = true; //@EIC not needed since updateSet[] is checked first //@EIC2 initialize all to null for insert row logic
+ }
+ }
+
+ // Initialize the data truncation. @B2A
+ if(connection_ != null) // @B2A
+ dataTruncation_ = ((AS400JDBCConnection) connection_).getProperties ().getBoolean (JDProperties.DATA_TRUNCATION); // @B2A
+ else // @B2A
+ dataTruncation_ = false;
+
+ // Trace messages.
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logOpen (this, statement_); // @J33a
+ JDTrace.logProperty (this, "Conncurrency", concurrency_);
+ JDTrace.logProperty (this, "Fetch direction", fetchDirection_);
+ JDTrace.logProperty (this, "Fetch size", fetchSize_);
+ JDTrace.logProperty (this, "Max rows", maxRows_);
+ JDTrace.logProperty (this, "Type", type_);
+ }
+ }
+
+
+
+ /**
+ Constructs an AS400JDBCResultSet object.
+
+ @param rowCache The row cache.
+ @param catalog The catalog.
+ @param cursorName The cursor name.
+ @param reply Reply object that must be returned to pool when result set closed
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This constructor is specifically for DatabaseMetaData
+ // result sets.
+ //
+ AS400JDBCResultSet (JDRowCache rowCache,
+ String catalog,
+ String cursorName,
+ AS400JDBCConnection con,
+ DBReplyRequestedDS reply) //@in2
+ throws SQLException
+ {
+ this (null, null, rowCache, catalog, cursorName, 0,
+ TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY,
+ FETCH_FORWARD, 0);
+
+ this.reply_ = reply;
+
+ //connection is needed in AS400JDBCResultsetMetadata. connection is passed in from AS400JDBCDatabaseMetaData
+ if(con != null) //@in2
+ connection_ = con; //@in2
+ }
+
+
+
+ /**
+ Checks that the result set is open. Public methods
+ that require an open result set should call this first.
+
+ @exception SQLException If the result set is not open.
+ **/
+ void checkOpen ()
+ throws SQLException
+ {
+ if(closed_)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+
+
+ /**
+ Clears any information associated with the current row.
+ In addition, all warnings are cleared.
+ **/
+ private void clearCurrentRow ()
+ throws SQLException
+ {
+ clearCurrentValue ();
+ clearWarnings ();
+
+ if(concurrency_ == CONCUR_UPDATABLE)
+ {
+ for(int i = 0; i < columnCount_; ++i)
+ {
+ updateNulls_[i] = true; //@IEC //@EIC2
+ updateDefaults_[i] = false; //@EIA
+ updateUnassigned_[i] = false; //@EIA
+ updateSet_[i] = false;
+ }
+ }
+ }
+
+
+
+ /**
+ Clears any information associated with the current value.
+ **/
+ private void clearCurrentValue ()
+ {
+ // Implicitly close the InputStream if left open.
+ if(openInputStream_ != null)
+ {
+ try
+ {
+ openInputStream_.close ();
+ }
+ catch(IOException e)
+ {
+ // Ignore the exception.
+ }
+ openInputStream_ = null;
+ }
+
+ // Implicitly close the InputStream if left open.
+ if(openReader_ != null)
+ {
+ try
+ {
+ openReader_.close ();
+ }
+ catch(IOException e)
+ {
+ // Ignore the exception.
+ }
+ openReader_ = null;
+ }
+ }
+
+
+
+
+ /**
+ 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 SQLException
+ {
+ sqlWarning_ = null;
+ }
+
+
+
+ /**
+ Releases the result set's resources immediately instead of
+ waiting for them to be automatically released.
+
+ @exception SQLException If an error occurs.
+ **/
+ public void close ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // 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;
+
+ rowCache_.close ();
+ if (reply_ != null) { reply_.returnToPool(); reply_ = null; }
+ closed_ = true;
+ if(statement_ != null)
+ statement_.notifyClose ();
+
+ // Close the delete statement if opened.
+ if(deleteStatement_ != null)
+ deleteStatement_.close ();
+
+ if(isMetadataResultSet == true) //@mdclose
+ statement_.close(); //@mdclose
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logClose (this);
+ }
+ }
+
+
+
+ /**
+ Closes the result set if not explicitly closed by the caller.
+
+ @exception Throwable If an error occurs.
+ **/
+ protected void finalize ()
+ throws Throwable
+ {
+ try{
+ if(! closed_) {
+ JDTrace.logInformation (this, "WARNING: Finalizer thread closing result set object.");
+ close ();
+ }
+ }
+ catch(Exception e){
+ //catch any exceptions and don't throw them
+ }
+ super.finalize ();
+ }
+
+
+
+ /**
+ Returns the column index for the specified column name.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.findColumn("\"MixedCase\"").
+
+ @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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return row_.findField ((columnName != null) ? columnName : "");
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the result set concurrency.
+
+ @return The result set concurrency. Valid values are:
+ Cursor names are case sensitive. However, when using a cursor
+ name within other SQL positioned UPDATE or DELETE statements,
+ the cursor name will be uppercased. If you use a cursor name
+ with lowercase characters, you need to enclose it in double
+ quotes when referring to it in other SQL statements.
+
+ @return The cursor name.
+
+ @exception SQLException If the result is not open.
+ **/
+ public String getCursorName ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return cursorName_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the fetch direction.
+
+ @return The fetch direction.
+ Valid values are:
+ This setting only affects statements that meet the criteria
+ specified in the "block criteria" property. The fetch size
+ is only used if the "block size" property is set to "0".
+
+ @param fetchSize 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 fetchSize)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ if((fetchSize < 0)
+ || ((fetchSize > maxRows_) && (maxRows_ > 0)))
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ checkOpen ();
+ fetchSize_ = fetchSize;
+
+ // This is a kludgy way of keeping the fetch size
+ // out of the JDRowCache interface. It only applies
+ // to JDServerRowCache anyway.
+ if(rowCache_ instanceof JDServerRowCache)
+ ((JDServerRowCache) rowCache_).setFetchSize (fetchSize_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Fetch size", fetchSize_);
+ }
+ }
+
+
+
+ /**
+ Returns the name of the SQL cursor in use by the result set.
+
+ @return The cursor name.
+ **/
+ public String toString ()
+ {
+ return cursorName_;
+ }
+
+
+
+ /*---------------------------------------------------------*/
+ /* */
+ /* CURSOR POSITIONING. */
+ /* */
+ /*---------------------------------------------------------*/
+
+
+
+ // Private data.
+ //
+ // Either position from first or last or both is set
+ // at any given moment, depending on what we can
+ // determine. Whether we can determine one or both of
+ // these depends on how the caller has positioned the
+ // cursor.
+ //
+ // For both of these values, 0 means after the last or
+ // before the first. -1 means not able to determine.
+ // @E1: a new constant is added which also means we
+ // don't know the value. -1 is not used because it
+ // is easy to incorrectly add 1 to -1 and make it look
+ // like a valid value (and a very hard bug to find).
+ // Adding 1 to -9999 results in a strange value which
+ // should be easier to debug.
+ //
+ // The position insert flag is set when the cursor
+ // is moved to the insert row.
+ //
+ // @E1: Fully supporting getRow() means at times
+ // looping through the rows to count them. Two
+ // values are added to reduce the amount rows we
+ // loop through. We update highestKnownRow and
+ // totalRows whenever possible to reduce the number
+ // of rows we loop through. Once set, these
+ // values do not change. That means if rows are added
+ // or deleted during the life of the rs, these
+ // constants will not reflect the change. I talked
+ // to the developer of the native driver and
+ // he feels it is safe (and much faster) to harden
+ // the values once they are set. The alternative
+ // is to create a property where the app can tell us
+ // to re-get the total at appropriate times. The
+ // performance of that would probably be unacceptably
+ // slow.
+ //
+
+ private static final int NOT_KNOWN = -9999; // @E1a
+
+ private int positionFromFirst_ = 0;
+ private int positionFromLast_ = -1;
+ private boolean positionInsert_ = false;
+ private boolean positionValid_ = false;
+
+ // totalRows_ is the number of rows in the RS. Highest
+ // known row is the biggest row we have reached so far. Eventually
+ // they will be the same but until there is a need to figure
+ // out how many rows are in the RS, total will be not-known and
+ // highest will increase.
+ private int totalRows_ = NOT_KNOWN; // @E1a
+ private int highestKnownRow_ = NOT_KNOWN; // @E1a
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to an absolute row number.
+
+ Attempting to move any number of positions before
+ the first row positions the cursor to before the first row.
+ Attempting to move beyond the last
+ row positions the cursor after the last row.
+
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @param rowNumber 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 rowNumber)
+ throws SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ // @E2a absolute(0) moves you to before the first row
+ if(rowNumber == 0) // @E2a
+ {
+ // @E2a
+ beforeFirst(); // @E2a
+ return false; // @E2a
+ } // @E2a
+
+
+ // Initialization.
+ beforePositioning (true);
+ // @E2d if (rowNumber == 0)
+ // @E2d JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID);
+
+ // Handle max rows.
+ // @E3, fixes to correctly handle maxRows, (1) Make sure
+ // we don't go before first when absolute < 0, and (2) make sure
+ // we get the row number right because the system and row cache
+ // do not deal with maxRows. They always deal with the entire
+ // result set.
+ //
+ // old code:
+ //
+ // if ((rowNumber > maxRows_) && (maxRows_ > 0))
+ // {
+ // afterLast ();
+ // return false;
+ // }
+ //
+ // new code:
+ if(maxRows_ > 0) // @E3a
+ {
+ // @E3a
+ if(rowNumber > 0) // @E3a
+ {
+ // @E3a
+ if(rowNumber > maxRows_) // @E3a
+ {
+ // @E3a
+ afterLast(); // @E3a
+ return false; // @E3a
+ } // @E3a
+ // Don't need an else. Drop through and call the rowCache as if maxRows not set.
+ } // @E3a
+ else
+ { // @E3a // @E3a
+ if(totalRows_ == NOT_KNOWN) // @E3a
+ {
+ // @E3a
+ findLastRow(); // @E3a
+ } // @E3a
+ int distanceFromFirst = totalRows_ + rowNumber; // @E3a
+ if(distanceFromFirst < 0) // @E3a
+ {
+ // @E3a
+ beforeFirst(); // @E3a
+ return false; // @E3a
+ } // @E3a
+ else // @E3a
+ rowNumber = distanceFromFirst + 1; // @E3a
+ // don't return. Drop through and call the rowCache as if maxRows not set.
+ } // @E3a
+ } // @E3a
+
+
+ // Position the cursor.
+ rowCache_.absolute (rowNumber);
+ positionValid_ = (rowCache_.isValid ());
+ if(rowNumber > 0)
+ {
+ positionFromFirst_ = positionValid_ ? rowNumber : -1;
+ positionFromLast_ = positionValid_ ? -1 : 0;
+
+ if(positionValid_) // @E1a
+ {
+ // @E1a
+ if(highestKnownRow_ < rowNumber) // @E1a
+ highestKnownRow_ = rowNumber; // @E1a
+
+ if(totalRows_ != NOT_KNOWN) // @E2a
+ positionFromLast_ = totalRows_ - rowNumber + 1; // @E2a
+ } // @E1a
+ }
+ else
+ {
+ positionFromFirst_ = positionValid_ ? -1 : 0;
+ positionFromLast_ = positionValid_ ? -rowNumber : -1;
+
+ if(positionValid_) // @E1a
+ {
+ // @E1a
+ if(totalRows_ != NOT_KNOWN) // @E2a
+ {
+ // @E2a
+ int currentRow = totalRows_ + rowNumber; // @E1a
+
+ if(highestKnownRow_ < currentRow) // @E1a
+ highestKnownRow_ = currentRow; // @E1a
+
+ positionFromFirst_ = currentRow + 1; // @E2a
+ } // @E1a
+ } // @E1a
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor after the last row.
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @exception SQLException If the result set is not open,
+ the result set is not scrollable,
+ or an error occurs.
+ **/
+ public void afterLast ()
+ throws SQLException
+ {
+ // @E1: Implementation simplified. Now do work in other methods
+ // that have to do the work anyway.
+ //
+ // Old code (v5r1 and older);
+ //
+ // synchronized(internalLock_) // @D1a
+ // {
+ // beforePositioning (true);
+ // rowCache_.afterLast ();
+ // positionFromFirst_ = -1;
+ // positionFromLast_ = 0;
+ // positionValid_ = false;
+ // }
+ //
+ // New code (note we don't do beforePositioning(true) because that is
+ // done in last())
+ //
+ synchronized(internalLock_)
+ {
+ last();
+ next();
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor before the first row.
+ If an InputStream from the current row is open, it is implicitly
+ closed. In addition, all warnings and pending updates are cleared.
+
+ @exception SQLException If the result set is not open,
+ the result set is not scrollable,
+ or an error occurs.
+ **/
+ public void beforeFirst ()
+ throws SQLException
+ {
+ // @E1: Implementation simplified. Now do work in other methods
+ // that have to do the work anyway.
+ //
+ // Old code (v5r1 and older);
+ //
+ // synchronized(internalLock_) // @D1A
+ // {
+ // beforePositioning (true);
+ // rowCache_.beforeFirst ();
+ // positionFromFirst_ = 0;
+ // positionFromLast_ = -1;
+ // positionValid_ = false;
+ // }
+ //
+ // New code (note we don't do beforePositioning(true) because that is
+ // done in last())
+ //
+ synchronized(internalLock_)
+ {
+ first();
+ previous();
+ positionFromLast_ = -1;//@GRA for returning correct value from getRow() after a select and insertRow()
+ }
+ }
+
+
+
+ /**
+ Checks necessary conditions before positioning a row. All
+ positioning methods should call this before changing the
+ position.
+
+ @param scrollable Indicates if the result set must be
+ scrollable.
+
+ @exception SQLException If the position cannot be done.
+ **/
+ private void beforePositioning (boolean scrollable)
+ throws SQLException
+ {
+ // Check to see if saved exception. If so, then create a copy with the
+ // proper stack trace and throw it, referencing the original exception @F3A
+ if (savedException_ != null) {
+ SQLException nextException = savedException_;
+ savedException_ = null;
+ JDError.throwSQLException(this, nextException);
+ }
+ checkOpen ();
+
+ if((scrollable) && (getType() == TYPE_FORWARD_ONLY)) //@cur
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ clearCurrentRow ();
+
+ // Get off of the insert row, if on it.
+ positionInsert_ = false;
+ }
+
+
+ // @E3 new method!
+ /**
+ Counts the number of rows in the result set. That number
+ is the number of rows that meet criteria or maxRows,
+ whichever is smaller. The result of this method is
+ internal variable "totalRows_" is set.
+
+ **** Callers of this method must reposition the rowCache
+ **** after calling this method! This method moves the only the
+ **** rowCache cursor. Since it no longer matches the result set cursor,
+ **** the caller must re-sync the two cursors.
+
+ @exception SQLException If it doesn't work.
+ **/
+ private void findLastRow ()
+ throws SQLException
+ {
+ checkOpen ();
+
+ // if we already know how many rows are in the result set simply return.
+ if(totalRows_ != NOT_KNOWN)
+ return;
+
+
+ if(highestKnownRow_ > 0)
+ {
+ // If we are already past the maximum number of rows (probably
+ // an error condition) simply re-set highestKnownRow (total
+ // Rows is reset at the end of this routine).
+ if(highestKnownRow_ >= maxRows_)
+ {
+ highestKnownRow_ = maxRows_;
+ }
+ else
+ {
+ // As a last resort set the cursor to the highest known
+ // row then loop through the rows until we hit the end.
+ rowCache_.absolute(highestKnownRow_);
+ rowCache_.next();
+
+ while(rowCache_.isValid())
+ {
+ highestKnownRow_ ++;
+
+ if((maxRows_ > 0) && (highestKnownRow_ == maxRows_))
+ break;
+
+ rowCache_.next();
+ }
+ }
+ }
+ // worst case, we don't have any idea how many rows are in the rs.
+ // Start at the beginning and loop through the rows until we hit the
+ // end or maxRows.
+ else
+ {
+ rowCache_.first();
+
+ if(! rowCache_.isValid())
+ {
+ return;
+ }
+ else
+ {
+ highestKnownRow_ = 0;
+ while(rowCache_.isValid())
+ {
+ highestKnownRow_ ++;
+
+ if((maxRows_ > 0) && (highestKnownRow_ == maxRows_))
+ break;
+
+ rowCache_.next();
+ }
+ }
+ }
+ totalRows_ = highestKnownRow_;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to the first row.
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ beforePositioning (true);
+ rowCache_.first ();
+
+ // If the result set is not empty, then mark the
+ // position as being on the first row.
+ if(rowCache_.isValid ())
+ {
+ positionFromFirst_ = 1;
+
+ if(totalRows_ == NOT_KNOWN) // @E1a
+ positionFromLast_ = -1;
+ else // @E1a
+ positionFromLast_ = totalRows_; // @E1a
+
+ positionValid_ = true;
+
+ if(highestKnownRow_ < 1) // @E1a
+ highestKnownRow_ = 1; // @E1a
+ }
+
+ // Otherwise, there is no first row (only true if ResultSet is empty)
+ else
+ {
+ positionFromFirst_ = -1;
+ positionFromLast_ = -1;
+ positionValid_ = false;
+ totalRows_ = 0; // @E1a
+ highestKnownRow_ = NOT_KNOWN; // @E1a
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+
+ // JDBC 2.0 @D2C
+ // @E1 entire method re-worked
+ /**
+ Returns the current row number, or 0.
+
+ 0 is returned if the cursor is not on a valid row (such as
+ before the first row, after the last row, or on the insert row),
+ or if the result set is empty.
+
+ This method may be slow if cursor movement based on the end
+ of the result set is used. Methods such as last(), afterLast()
+ and absolute() with a negative value will move the cursor based
+ on the end of the result set. This method will be slow in these
+ cases because internally the method must get every row to determine
+ how many rows are in the result set before calculating the current
+ row. The system does not know how many rows are in the result
+ set until every row is touched. That is why this method may
+ start at the highest row retrieved so far, then do next() until
+ the last row is retrieved.
+
+ Once the maximum number of rows in the result set is determined,
+ it does not change until the result set is closed.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ checkOpen ();
+
+ // @E1
+ // Old Code:
+ // return ((positionFromFirst_ > 0) && (positionInsert_ == false))
+ // ? positionFromFirst_ : 0;
+ //
+ // Old code in more readable format:
+ // if ((positionFromFirst_ > 0) && (positionInsert_ == false))
+ // return positionFromFirst_;
+ // else
+ // return 0;
+ //
+ // case 1: return 0 if not on a valid row.
+ if((positionInsert_ == true) ||
+ (positionValid_ == false) ||
+ (isBeforeFirst()) ||
+ (isAfterLast()))
+ return 0;
+
+ // case 2: we know what the current row is because scrolling has been
+ // from the beginning of the result set, or because previous
+ // method calls calculated the value.
+ if(positionFromFirst_ > 0)
+ return positionFromFirst_;
+
+ // case 3a: don't know the current row because negative scrolling or
+ // scrolling from end has been used, *** and we are currently
+ // at the end of the rs ***. If we don't know the number of
+ // rows in the rs we will move the cursor to the highest
+ // known row then do next() until we get to the end.
+ if(isLast())
+ {
+ if(totalRows_ != NOT_KNOWN)
+ {
+ positionFromFirst_ = totalRows_;
+ return positionFromFirst_;
+ }
+ else
+ {
+ if(highestKnownRow_ == NOT_KNOWN)
+ first();
+ else
+ absolute(highestKnownRow_);
+
+ while(next())
+ {
+ }
+ previous();
+
+ return positionFromFirst_;
+ }
+ }
+
+ // case 3b: don't know the current row because negative scrolling or
+ // scrolling from end has been used, *** but we are not currently
+ // at the end of the rs ***. If we don't know how many rows are
+ // in the result set we will move the cursor to the highest known
+ // row then do next() until we get back to where we were.
+ if(positionFromLast_ > 0)
+ {
+ if(totalRows_ != NOT_KNOWN)
+ {
+ positionFromFirst_ = totalRows_ - positionFromLast_ + 1;
+ return positionFromFirst_;
+ }
+ else
+ {
+ int currentPositionFromLast = positionFromLast_;
+
+ if(highestKnownRow_ == NOT_KNOWN)
+ first();
+ else
+ absolute(highestKnownRow_);
+
+ while(next())
+ {
+ }
+ absolute(totalRows_ - currentPositionFromLast + 1);
+
+ return positionFromFirst_;
+ }
+ }
+
+ // case 4: We don't have a clue how to figure out what the current row is. Return 0;
+ if(JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "Could not determine row number in getRow().");
+
+ return 0;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return((positionFromLast_ == 0)
+ && (positionFromFirst_ != 0)
+ && (positionInsert_ == false)
+ && (! rowCache_.isEmpty ()));
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return((positionFromFirst_ == 0)
+ && (positionFromLast_ != 0)
+ && (positionInsert_ == false)
+ && (! rowCache_.isEmpty ()));
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return((positionFromFirst_ == 1) && (positionInsert_ == false));
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ checkOpen ();
+ // @E2c -- Problem: if scrolling forward we don't know
+ // if we are on the last row until next() is called.
+ // In this case isLast() never returns true because
+ // by the time we figure out we are out of rows we
+ // are afterLast. The fix is to internally call
+ // next then previous if we don't figure out we
+ // are on the last row some othe way. This will be
+ // slower but accurate.
+ //
+ // Old code:
+ //
+ // return (((positionFromLast_ == 1) ||
+ // ((positionFromFirst_ == maxRows_) && (maxRows_ > 0)))
+ // && (positionInsert_ == false));
+ //
+ // New code:
+ if((positionInsert_ == true) || (positionFromLast_ > 1) || (positionValid_ == false))
+ return false;
+
+ if(( positionFromLast_ == 1) ||
+ ((positionFromFirst_ == maxRows_) && (maxRows_ > 0)))
+ return true;
+
+ boolean returnValue = ! next();
+ previous();
+
+ return returnValue;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to the last row.
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ beforePositioning (true);
+
+ if(maxRows_ > 0) // @E3a
+ {
+ // @E3a
+ findLastRow(); // @E3a
+ // @E3a
+ if(totalRows_ >= maxRows_) // @E3a
+ {
+ rowCache_.absolute(maxRows_); // @E3a
+ }
+ else
+ { // @E3a
+ rowCache_.last (); // @E3a
+ }
+ } // @E3a
+ else
+ rowCache_.last();
+
+ // If the result set is not empty, then mark the
+ // position as being on the last row.
+ if(rowCache_.isValid ())
+ {
+ positionFromFirst_ = -1;
+ positionFromLast_ = 1;
+ positionValid_ = true;
+
+ if(totalRows_ != NOT_KNOWN) // @E1a
+ {
+ // @E1a
+ positionFromFirst_ = totalRows_; // @E1a
+ } // @E1a
+ }
+
+ // Otherwise, there is no last row (only when result set is empty?)
+ else
+ {
+ positionFromFirst_ = -1;
+ positionFromLast_ = -1;
+ positionValid_ = false;
+ totalRows_ = 0; // @E1a
+ highestKnownRow_ = NOT_KNOWN; // @E1a
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to the current row. This is the row
+ where the cursor was positioned before moving it to the insert
+ row. If the cursor is not on the insert row, then this
+ has no effect.
+
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @exception SQLException If the result set is not open,
+ the result set is not scrollable,
+ or an error occurs.
+ **/
+ public void moveToCurrentRow ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ beforePositioning (true);
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to the insert row.
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ beforePositioning (true);
+ beforeUpdate ();
+ positionInsert_ = true;
+ }
+ }
+
+
+
+ /**
+ Positions the cursor to the next row.
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Initialization.
+ beforePositioning (false);
+
+ // Handle max rows.
+ if((maxRows_ > 0) && (positionFromFirst_ >= maxRows_))
+ {
+ // @B3D afterLast ();
+ // @E3D rowCache_.afterLast (); // @B3a
+ rowCache_.absolute(maxRows_ + 1); // @E3a
+ positionFromFirst_ = -1; // @B3A
+ positionFromLast_ = 0; // @B3A
+ positionValid_ = false; // @B3A
+
+ totalRows_ = maxRows_; // @E1a
+ highestKnownRow_ = maxRows_; // @E1a
+
+ return false;
+ }
+
+ // Normal case. If the row is null after a next, then
+ // the cursor is positioned after the last row.
+ rowCache_.next();
+
+ if(rowCache_.isValid ())
+ {
+ if(positionFromFirst_ >= 0)
+ ++positionFromFirst_;
+
+ if(positionFromLast_ > 0)
+ --positionFromLast_;
+
+ if(positionFromFirst_ >= 0) // @E1a
+ if(highestKnownRow_ < positionFromFirst_) // @E1a
+ highestKnownRow_ = positionFromFirst_; // @E1a
+
+ positionValid_ = true;
+
+ }
+ else
+ {
+ // If this is the first time row has been null,
+ // then increment one more time.
+ // @E2a only if there are rows in the rs!
+ if(! rowCache_.isEmpty ()) // @E2a
+ {
+ if(positionFromLast_ != 0)
+ {
+ if(positionFromFirst_ >= 0)
+ {
+ totalRows_ = positionFromFirst_; // @E2a
+ ++positionFromFirst_;
+ }
+ }
+ positionFromLast_ = 0;
+ } // @E2a
+ else
+ { // @E1a // @E1a
+ if(highestKnownRow_ > 0) // @E1a
+ {
+ // @E1a
+ totalRows_ = highestKnownRow_; // @E1a
+ positionFromFirst_ = totalRows_; // @E1a
+ positionFromLast_ = 0; // @E1a
+ } // @E1a
+ } // @E1a
+ positionValid_ = false;
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Positions the cursor to the previous row.
+ If an InputStream from the current row is open, it is implicitly
+ closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_) // @D1A
+ {
+ // Initialization.
+ beforePositioning (true);
+
+ // Normal case. If the row is null after a previous, then
+ // the cursor is positioned before the first row.
+ rowCache_.previous();
+
+ if(rowCache_.isValid ())
+ {
+ if(positionFromFirst_ > 0)
+ --positionFromFirst_;
+
+ if(positionFromLast_ >= 0)
+ ++positionFromLast_;
+
+ positionValid_ = true;
+ }
+ else
+ {
+ // If this is the first time row has been null,
+ // then increment one more time.
+ if(positionFromFirst_ != 0)
+ if(positionFromLast_ >= 0)
+ ++positionFromLast_;
+
+ positionFromFirst_ = 0;
+ positionValid_ = false;
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+ // JDBC 2.0
+ /**
+ Refreshes the current row from the database and cancels all
+ pending updates that have been made since the last call to
+ updateRow(). This method provides a way for an application
+ to explicitly refetch a row from the database. If an InputStream
+ from the current row is open, it is implicitly closed. In
+ addition, all warnings and pending updates are cleared.
+
+ @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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ if(positionInsert_ == true)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ beforePositioning (true);
+ if(positionValid_ == false)
+ JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID);
+
+ if(concurrency_ == CONCUR_UPDATABLE)
+ for(int i = 0; i < columnCount_; ++i)
+ updateSet_[i] = false;
+
+ rowCache_.refreshRow ();
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+
+ If an InputStream from the current row is open, it is
+ implicitly closed. In addition, all warnings and pending updates
+ are cleared.
+
+ @param rowNumber 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 rowNumber)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Initialization.
+ beforePositioning (true);
+ //if((positionFromFirst_ == 0) || (positionFromLast_ == 0)) //@rel1 per javadoc, relative(1) <==> next()
+ //return false;
+
+ // If before first and scrolling negative, then the position is invalid.
+ // return without doing anything..
+ if (rowNumber < 0 && isBeforeFirst()) {
+ return false;
+ }
+
+
+ // Handle max rows.
+ if((maxRows_ > 0) && (positionFromFirst_ == -1)) // @E3a
+ getRow(); // @E3a
+
+ if((positionFromFirst_ >= 0)
+ && (positionFromFirst_ + rowNumber > maxRows_)
+ && (maxRows_ > 0))
+ { // @E3a
+ afterLast(); // should this be absolute(max+1) // @E3a
+ return false;
+ } // @E3a
+
+
+ // Normal case. If the row is null after relative,
+ // then we are off the edge of the result set.
+ rowCache_.relative (rowNumber);
+
+ if(rowCache_.isValid ())
+ {
+ if(positionFromFirst_ >= 0)
+ positionFromFirst_ += rowNumber;
+
+ if(positionFromLast_ >= 0)
+ positionFromLast_ -= rowNumber;
+
+ positionValid_ = true;
+
+ if(positionFromFirst_ >= 0) // @E1a
+ if(highestKnownRow_ < positionFromFirst_) // @E1a
+ highestKnownRow_ = positionFromFirst_; // @E1a
+
+ }
+ else
+ {
+ if(rowNumber >= 0)
+ {
+ positionFromFirst_ = -1;
+ positionFromLast_ = 0;
+ }
+ else
+ {
+ positionFromFirst_ = 0;
+ positionFromLast_ = -1;
+ }
+ positionValid_ = false;
+ }
+
+ return positionValid_;
+ }
+ }
+
+
+
+ /*---------------------------------------------------------*/
+ /* */
+ /* GET DATA METHODS. */
+ /* */
+ /*---------------------------------------------------------*/
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as an Array object.
+ DB2 for IBM i does not support arrays.
+
+ @param columnIndex 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 arrays.
+ **/
+ public Array getArray (int columnIndex)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as an Array object.
+ DB2 for IBM i does not support arrays.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getArray("\"MixedCase\"").
+
+ @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 arrays.
+ **/
+ public Array getArray (String columnName)
+ throws SQLException
+ {
+ return getArray (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of ASCII
+ characters. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ BLOB. All of the data in the returned stream must be read
+ prior to getting the value of any other column. The next
+ call to a get method implicitly closes the stream.
+
+ @param columnIndex 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 InputStream getAsciiStream (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ InputStream value = (data == null) ? null : data.getAsciiStream ();
+ openInputStream_ = value;
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of ASCII
+ characters. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ BLOB. All of the data in the returned stream must be read
+ prior to getting the value of any other column. The next
+ call to a get method implicitly closes the stream.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getAsciiStream("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public InputStream getAsciiStream (String columnName)
+ throws SQLException
+ {
+ return getAsciiStream (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ // @D0C
+ /**
+ Returns the value of a column as a BigDecimal object. This
+ can be used to get values from columns with SQL types
+ SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 BigDecimal getBigDecimal (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ BigDecimal value = (data == null) ? null : data.getBigDecimal (-1);
+ testDataTruncation (columnIndex, data, false); //@trunc getBigDecimal(int) can set truncation_!=0, but we should not throw an SQLEception
+ return value;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ // @D0C
+ /**
+ Returns the value of a column as a BigDecimal object. This
+ can be used to get values from columns with SQL types
+ SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBigDecimal("\"MixedCase\"").
+
+ @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 name is not found,
+ or the requested conversion is not valid.
+ **/
+ public BigDecimal getBigDecimal (String columnName)
+ throws SQLException
+ {
+ return getBigDecimal (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a BigDecimal object. This
+ can be used to get values from columns with SQL types
+ SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 BigDecimal getBigDecimal (int columnIndex, int scale)
+ throws SQLException
+ {
+ // Check for negative scale.
+ if(scale < 0)
+ JDError.throwSQLException (JDError.EXC_SCALE_INVALID,""+scale);
+
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ BigDecimal value = (data == null) ? null : data.getBigDecimal (scale);
+ testDataTruncation (columnIndex, data, false); //@trunc getBigDecimal(int) can set truncation_!=0, but we should not throw an SQLEception
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a BigDecimal object. This
+ can be used to get values from columns with SQL types
+ SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBigDecimal("\"MixedCase\"", 0).
+
+ @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 name is not found,
+ the scale is not valid, or the
+ requested conversion is not valid.
+
+ @deprecated Use getBigDecimal(String) instead.
+ @see #getBigDecimal(String)
+ **/
+ public BigDecimal getBigDecimal (String columnName, int scale)
+ throws SQLException
+ {
+ return getBigDecimal (findColumn (columnName), scale);
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of uninterpreted
+ bytes. This can be used to get values from columns
+ with SQL types BINARY, VARBINARY, and BLOB. All of the data in
+ the returned stream must be read prior to getting the
+ value of any other column. The next call to a get method
+ implicitly closes the stream.
+
+ @param columnIndex 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 InputStream getBinaryStream (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ InputStream value = (data == null) ? null : data.getBinaryStream ();
+ openInputStream_ = value;
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of uninterpreted
+ bytes. This can be used to get values from columns
+ with SQL types BINARY, VARBINARY, and BLOB. All of the data in
+ the returned stream must be read prior to getting the
+ value of any other column. The next call to a get method
+ implicitly closes the stream.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBinaryStream("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public InputStream getBinaryStream (String columnName)
+ throws SQLException
+ {
+ return getBinaryStream (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Blob object.
+ This can be used to get values from columns with SQL
+ types BINARY, VARBINARY, and BLOB.
+
+ @param columnIndex 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 Blob getBlob (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Blob value = (data == null) ? null : data.getBlob ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Blob object.
+ This can be used to get values from columns with SQL
+ types BINARY, VARBINARY, and BLOB.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBlob("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Blob getBlob (String columnName)
+ throws SQLException
+ {
+ return getBlob (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java boolean value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex The column index (1-based).
+ @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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ boolean value = (data == null) ? false : data.getBoolean ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java boolean value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBoolean("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public boolean getBoolean (String columnName)
+ throws SQLException
+ {
+ return getBoolean (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java byte value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 byte getByte (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ byte value = (data == null) ? 0 : data.getByte ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java byte value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getByte("\"MixedCase\"").
+
+ @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 byte getByte (String columnName)
+ throws SQLException
+ {
+ return getByte (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the value of a column as a Java byte array.
+ This can be used to get values from columns with SQL
+ types BINARY and VARBINARY.
+
+ 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 columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ int sqlType = 0;
+ if (data != null) {
+ sqlType = data.getSQLType();
+ }
+ byte[] value; // @C1C
+
+ // Treat this differently from the other get's. If the data is not a // @C1A
+ // BINARY, VARBINARY, or BLOB, and we have access to the bytes, then return // @C1A @D4C
+ // the bytes directly. // @C1A
+ if((data != null)
+ && (!(sqlType == SQLData.BINARY))
+ && (!(sqlType == SQLData.VARBINARY))
+ && (!(sqlType == SQLData.BLOB)) // @D4A
+ && (!(sqlType == SQLData.BLOB_LOCATOR)) // @D4A
+ && (!(sqlType == SQLData.CHAR_FOR_BIT_DATA)) // @M0A
+ && (!(sqlType == SQLData.LONG_VARCHAR_FOR_BIT_DATA)) // @M0A
+ && (!(sqlType == SQLData.VARCHAR_FOR_BIT_DATA)) // @M0A
+ && (!(sqlType == SQLData.ROWID)) // @M0A
+ && (!(sqlType == SQLData.XML_LOCATOR)) //@xml3
+ && (row_ instanceof JDServerRow)) { // @C1A
+ value = ((JDServerRow)row_).getRawBytes(columnIndex); // @C1A
+ // @C1A
+
+ // If the data is a variable length type, we want to strip the encoded
+ // length to be consistent with other JDBC drivers
+ if (sqlType == SQLData.VARCHAR ||
+ sqlType == SQLData.VARGRAPHIC ||
+ sqlType == SQLData.NVARCHAR ||
+ sqlType == SQLData.DATALINK) {
+ if (value != null) {
+ if (value.length >= 2) {
+ int newLength = 0x100 * (((int)value[0])&0xff) + (((int)value[1])&0xff);
+ if (sqlType == SQLData.VARGRAPHIC) {
+ newLength = newLength * 2;
+ }
+ byte[] newValue = new byte[newLength];
+ for (int i = 0; i < newLength; i++) {
+ newValue[i] = value[i+2];
+ }
+ value = newValue;
+
+ }
+ }
+ } else if (sqlType == SQLData.CLOB_LOCATOR) {
+ String x = data.getString();
+ try {
+ value = x.getBytes("ISO8859_1");
+ } catch (Exception cpException) {
+ // ignore;
+ }
+ } else if (sqlType == SQLData.DBCLOB_LOCATOR) {
+ String x = data.getString();
+ try {
+ value = x.getBytes("UTF-16BE");
+ } catch (Exception cpException) {
+ // ignore;
+ }
+ }
+ }
+ else
+ { // @C1A
+ value = (data == null) ? null : data.getBytes (); // @C1C
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ } // @C1A
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a Java byte array.
+ This can be used to get values from columns with SQL
+ types BINARY and VARBINARY.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getBytes("\"MixedCase\"").
+
+ 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public byte[] getBytes (String columnName)
+ throws SQLException
+ {
+ return getBytes (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a character stream.
+ This can be used to to get values from columns with SQL
+ types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and BLOB.
+ All of the data in the returned stream must be read prior to
+ getting the value of any other column. The next call to a get
+ method implicitly closes the stream.
+
+ @param columnIndex 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 Reader getCharacterStream (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Reader value = (data == null) ? null : data.getCharacterStream ();
+ openReader_ = value;
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a character stream.
+ This can be used to to get values from columns with SQL
+ types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and BLOB.
+ All of the data in the returned stream must be read prior
+ to getting the value of any other column. The next call
+ to a get method implicitly closes the stream.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getCharacterStream("\"MixedCase\"").
+
+ @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 name is not valid, or the
+ requested conversion is not valid.
+ */
+ public Reader getCharacterStream (String columnName)
+ throws SQLException
+ {
+ return getCharacterStream (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Clob object.
+ This can be used to get values from columns with SQL
+ types CHAR, VARCHAR, BINARY, VARBINARY, BLOB, and CLOB.
+
+ @param columnIndex 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 Clob getClob (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Clob value = (data == null) ? null : data.getClob ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Clob object.
+ This can be used to get values from columns with SQL
+ types CHAR, VARCHAR, BINARY, VARBINARY, BLOB, and CLOB.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getClob("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Clob getClob (String columnName)
+ throws SQLException
+ {
+ return getClob (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Date object using
+ the default calendar. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+
+ @param columnIndex 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 Date getDate (int columnIndex)
+ throws SQLException
+ {
+ //@P0D return getDate (columnIndex, AS400Calendar.getGregorianInstance ());
+ return internalGetDate(columnIndex, null); //@P0A
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Date object using
+ the default calendar. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getDate("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Date getDate (String columnName)
+ throws SQLException
+ {
+ //@P0D return getDate (findColumn (columnName), AS400Calendar.getGregorianInstance ());
+ return internalGetDate(findColumn(columnName), null); //@P0A
+ }
+
+
+ //@P0A - Moved out of getDate()
+ private Date internalGetDate(int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Date value = (data == null) ? null : data.getDate (calendar);
+ testDataTruncation (columnIndex, data, false); //@trunc getDate() can set truncation_!=0, but we should not throw an SQLEception
+ return value;
+ }
+ }
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Date object using
+ a calendar other than the default. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+
+ @param columnIndex 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.
+ **/
+ public Date getDate (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ // Check for null calendar.
+ if(calendar == null)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+ return internalGetDate(columnIndex, calendar); //@P0C
+ /*@P0M
+ synchronized(internalLock_) { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Date value = (data == null) ? null : data.toDate (calendar);
+ testDataTruncation (columnIndex, data);
+ return value;
+ }
+ */ //@P0M
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Date object using
+ a calendar other than the default. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getDate("\"MixedCase\"", 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 name is not found,
+ the calendar is null, or the
+ requested conversion is not valid.
+ **/
+ public Date getDate (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getDate (findColumn (columnName), calendar);
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java double value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 double getDouble (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ double value = (data == null) ? 0 : data.getDouble ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java double value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getDouble("\"MixedCase\"").
+
+ @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 SQLException
+ {
+ return getDouble (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java float value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ float value = (data == null) ? 0 : data.getFloat ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java float value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getFloat("\"MixedCase\"").
+
+ @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 float getFloat (String columnName)
+ throws SQLException
+ {
+ return getFloat (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java int value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 int getInt (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ int value = (data == null) ? 0 : data.getInt ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java int value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getInt("\"MixedCase\"").
+
+ @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 SQLException
+ {
+ return getInt (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java long value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ long value = (data == null) ? 0 : data.getLong ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java long value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getLong("\"MixedCase\"").
+
+ @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 long getLong (String columnName)
+ throws SQLException
+ {
+ return getLong (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the ResultSetMetaData object that describes the
+ result set's columns.
+
+ @return The metadata object.
+
+ @exception SQLException If an error occurs.
+ **/
+ public ResultSetMetaData getMetaData ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ ConvTable convTable = null; // @G5A
+ DBExtendedColumnDescriptors extendedDescriptors = null; // @G5A
+ // If a DMD method (internal call), statement_ will be null because we don't really have // @G5A
+ // a statement object // @G5A
+ if(statement_ != null) // @G5A
+ {
+ // @G5A
+ extendedDescriptors = statement_.getExtendedColumnDescriptors(); // @G5A
+ // If we have extendedDescriptors, send a ConvTable to convert them, else pass null // @G5A
+ if(extendedDescriptors != null) // @G5A
+ {
+ // @G5A
+ convTable = ((AS400JDBCConnection)connection_).converter_; // @G5A
+ } // @G5A
+ } // @G5A
+ return new AS400JDBCResultSetMetaData (catalog_, concurrency_,
+ cursorName_, row_,
+ extendedDescriptors, convTable, connection_); // @G5A //@in1
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a Java Object.
+ This can be used to get values from columns with all
+ SQL types. If the column is a user-defined type, then the
+ connection's type map is used to created the object.
+
+ @param columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Object value = (data == null) ? null : data.getObject ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a Java Object.
+ This can be used to get values from columns with all
+ SQL types. If the column is a user-defined type, then the
+ connection's type map is used to created the object.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getObject("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Object getObject (String columnName)
+ throws SQLException
+ {
+ return getObject (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Java Object.
+
+ @param columnIndex The column index (1-based).
+ @param typeMap 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 columnIndex, Map typeMap)
+ throws SQLException
+ {
+ // Check for null type map, even though we don't use it.
+ if(typeMap == null)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ return getObject (columnIndex);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Java Object.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getObject("\"MixedCase\"", typeMap).
+
+ @param columnName The column name.
+ @param typeMap 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 name is not found,
+ the type map is null, or the
+ requested conversion is not valid.
+ **/
+ public Object getObject (String columnName, Map typeMap)
+ throws SQLException
+ {
+ // Check for null type map, even though we don't use it.
+ if(typeMap == null)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ return getObject (findColumn (columnName));
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Ref object.
+ DB2 for IBM i does not support structured types.
+
+ @param columnIndex 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 Ref getRef (int columnIndex)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a Ref object.
+ DB2 for IBM i does not support structured types.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getRef("\"MixedCase\"").
+
+ @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 Ref getRef (String columnName)
+ throws SQLException
+ {
+ return getRef (findColumn (columnName));
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java short value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+
+ @param columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ short value = (data == null) ? 0 : data.getShort ();
+ testDataTruncation (columnIndex, data, true); //@trunc
+ return value;
+ }
+ }
+
+
+
+ // @D0C
+ /**
+ Returns the value of a column as a Java short value.
+ This can be used to get values from columns with SQL
+ types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ NUMERIC, CHAR, and VARCHAR.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getShort("\"MixedCase\"").
+
+ @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 short getShort (String columnName)
+ throws SQLException
+ {
+ return getShort (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the value of a column as a String object.
+ This can be used to get values from columns with any SQL
+ type.
+
+ @param columnIndex 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 String getString (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ String value = (data == null) ? null : data.getString ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a String object.
+ This can be used to get values from columns with any SQL
+ type.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getString("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public String getString (String columnName)
+ throws SQLException
+ {
+ return getString (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Time object using the
+ default calendar. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+
+ @param columnIndex 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 Time getTime (int columnIndex)
+ throws SQLException
+ {
+ //@P0D return getTime (columnIndex, AS400Calendar.getGregorianInstance ());
+ return internalGetTime(columnIndex, null); //@P0A
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Time object using the
+ default calendar. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getTime("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Time getTime (String columnName)
+ throws SQLException
+ {
+ //@P0D return getTime (findColumn (columnName), AS400Calendar.getGregorianInstance ());
+ return internalGetTime(findColumn(columnName), null); //@P0A
+ }
+
+ //@P0M - Moved out of getTime()
+ private Time internalGetTime(int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Time value = (data == null) ? null : data.getTime (calendar);
+ testDataTruncation (columnIndex, data, false); //@trunc getTime() can set truncation_!=0, but we should not throw an SQLEception
+ return value;
+ }
+ }
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Time object using a
+ calendar other than the default. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+
+ @param columnIndex 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.
+ **/
+ public Time getTime (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ //@P0D synchronized(internalLock_) { // @D1A
+ // Check for null calendar.
+ if(calendar == null)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+ return internalGetTime(columnIndex, calendar); //@P0C
+ /*@P0M
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Time value = (data == null) ? null : data.toTime (calendar);
+ testDataTruncation (columnIndex, data);
+ return value;
+ }
+ */ //@P0M
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Time object using a
+ calendar other than the default. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getTime("\"MixedCase\"", 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 name is not found,
+ the calendar is null, or the
+ requested conversion is not valid.
+ **/
+ public Time getTime (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getTime (findColumn (columnName), calendar);
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Timestamp object
+ using the default calendar. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+
+ @param columnIndex 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 Timestamp getTimestamp (int columnIndex)
+ throws SQLException
+ {
+ //@P0D return getTimestamp (columnIndex, AS400Calendar.getGregorianInstance ());
+ return internalGetTimestamp(columnIndex, null); //@P0A
+ }
+
+
+
+ /**
+ Returns the value of a column as a java.sql.Timestamp object
+ using the default calendar. This can be used to get values
+ from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getTimestamp("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public Timestamp getTimestamp (String columnName)
+ throws SQLException
+ {
+ //@P0D return getTimestamp (findColumn (columnName), AS400Calendar.getGregorianInstance ());
+ return internalGetTimestamp(findColumn(columnName), null); //@P0A
+ }
+
+ //@P0M - Moved out of getTimestamp()
+ private Timestamp internalGetTimestamp(int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Timestamp value = (data == null) ? null : data.getTimestamp (calendar);
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Timestamp object
+ using a calendar other than the default. This can be used to
+ get values from columns with SQL types CHAR, VARCHAR, DATE,
+ and TIMESTAMP.
+
+ @param columnIndex 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.
+ **/
+ public Timestamp getTimestamp (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ // Check for null calendar.
+ if(calendar == null)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+ return internalGetTimestamp(columnIndex, calendar);
+ /*@P0M
+ synchronized(internalLock_) { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ Timestamp value = (data == null) ? null : data.toTimestamp (calendar);
+ testDataTruncation (columnIndex, data);
+ return value;
+ }
+ */ //@P0M
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the value of a column as a java.sql.Timestamp object
+ using a calendar other than the default. This can be used to
+ get values from columns with SQL types CHAR, VARCHAR, DATE,
+ and TIMESTAMP.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getTimestamp("\"MixedCase\"", 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 name is not found,
+ the calendar is null, or the
+ requested conversion is not valid.
+ **/
+ public Timestamp getTimestamp (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getTimestamp (findColumn (columnName), calendar);
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of Unicode
+ characters. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ BLOB. All of the data in the returned stream must be read
+ prior to getting the value of any other column. The next
+ call to a get method implicitly closes the stream.
+
+ @param columnIndex 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 InputStream getUnicodeStream (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // Get the data and check for SQL NULL.
+ SQLData data = getValue (columnIndex);
+ InputStream value = (data == null) ? null : data.getUnicodeStream ();
+ openInputStream_ = value;
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+
+ /**
+ Returns the value of a column as a stream of Unicode
+ characters. This can be used to get values from columns
+ with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB,
+ and BLOB. All of the data in the returned stream must be
+ read prior to getting the value of any other column. The
+ next call to a get method implicitly closes the stream.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.getUnicodeStream("\"MixedCase\"").
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+
+ @deprecated Use getCharacterStream(String) instead.
+ @see #getCharacterStream(String)
+ **/
+ public InputStream getUnicodeStream (String columnName)
+ throws SQLException
+ {
+ return getUnicodeStream (findColumn (columnName));
+ }
+
+
+
+ /**
+ Returns a piece of row data for the specified index,
+ and perform all appropriate validation. Also check
+ for SQL NULL.
+
+ @param columnIndex 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.
+ **/
+ private SQLData getValue (int columnIndex)
+ throws SQLException
+ {
+ checkOpen ();
+ clearCurrentValue ();
+
+ // Check that there is a current row.
+ if((positionValid_ == false) && (positionInsert_ == false))
+ JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID);
+
+ // Validate The column index.
+ if((columnIndex < 1) || (columnIndex > columnCount_))
+ JDError.throwSQLException (JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if an update was made or we are on the insert
+ // row.
+ if(concurrency_ == CONCUR_UPDATABLE)
+ {
+ if((updateSet_[columnIndex-1] == true) //@EIC2 changed back to original logic. For case of after insertrow is inserted, the updateSet[] is reset, but can still have non-null data.
+ || (positionInsert_ == true))
+ {
+ wasNull_ = updateNulls_[columnIndex-1];
+ wasDataMappingError_ = false;
+ if(wasNull_)
+ return null;
+ else
+ return updateRow_.getSQLData (columnIndex);
+ }
+ }
+
+ // Get the data and check for SQL NULL. @A1C
+ wasNull_ = row_.isNull (columnIndex);
+ wasDataMappingError_ = row_.isDataMappingError(columnIndex);
+
+ //@KBL if a locator is used, tell the statement associated with it
+ SQLData sqlData = row_.getSQLType(columnIndex); //@KBL
+ int sqlType = sqlData.getSQLType(); //@xml3
+ if((sqlType == SQLData.CLOB_LOCATOR || //@KBL
+ sqlType == SQLData.BLOB_LOCATOR || //@KBL
+ sqlType == SQLData.DBCLOB_LOCATOR || //@KBL //@pdc jdbc40
+ sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
+ sqlType == SQLData.XML_LOCATOR)
+ && statement_ != null) //@mdrs2 //@xml3
+ statement_.setAssociatedWithLocators(true); //@KBL
+
+ if(wasNull_ || wasDataMappingError_)
+ return null;
+ else
+ return row_.getSQLData (columnIndex);
+ }
+
+
+
+ /**
+ Tests if a DataTruncation occurred on the read of a piece of
+ data and posts a DataTruncation warning if so.
+
+ @param columnIndex The column 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.
+ **/
+ private void testDataTruncation (int columnIndex, SQLData data, boolean exceptionOnTrunc) throws SQLException //@trunc
+ {
+ if(wasDataMappingError_)
+ {
+ postWarning(new DataTruncation(columnIndex, false, true, -1, -1));
+ }
+
+ if(data != null)
+ {
+ int truncated = data.getTruncated ();
+ if(truncated > 0)
+ {
+ //if 610 and number data type and called on certain getX() methods, then throw SQLException
+ //if 610, follow Native driver to thow exc if data is text and getX() is a number type getter method.
+ if((((AS400JDBCConnection)connection_).getVRM() >= JDUtilities.vrm610) && (exceptionOnTrunc == true)) //@trunc //@trunc2 only use exceptionOnTrunc as flag
+ { //@trunc
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); //@trunc
+ } //@trunc
+ int actualSize = data.getActualSize ();
+ postWarning (new DataTruncation (columnIndex, false, true,
+ actualSize, actualSize - truncated));
+ }
+ }
+ }
+
+
+
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return wasNull_;
+ }
+ }
+
+
+
+ /*---------------------------------------------------------*/
+ /* */
+ /* UPDATE DATA METHODS. */
+ /* */
+ /*---------------------------------------------------------*/
+
+
+
+ /**
+ Checks necessary conditions before updating a row. All
+ update methods should call this before updating.
+
+ @exception SQLException If the result set is not open
+ or the result set is not updatable.
+ **/
+ private void beforeUpdate ()
+ throws SQLException
+ {
+ checkOpen ();
+
+ if(concurrency_ != CONCUR_UPDATABLE)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Cancels all pending updates that have been made since the last
+ call to updateRow(). If no updates have been made or updateRow()
+ has already been called, then this method has no effect.
+
+ @exception SQLException If the result set is not open
+ or the result set is not updatable.
+ **/
+ public void cancelRowUpdates ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ beforeUpdate ();
+
+ for(int i = 0; i < columnCount_; ++i)
+ updateSet_[i] = false;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ beforeUpdate ();
+
+ if(positionValid_ == false) // @D9a
+ JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID); // @D9a
+
+ if(positionInsert_ == true)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ if(JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "Deleting a row.");
+
+ // Prepare the delete statement the first time
+ // we need it.
+ if(deleteStatement_ == null)
+ { // @D3C
+ StringBuffer buffer = new StringBuffer(); // @D3A
+ buffer.append("DELETE FROM "); // @D3A
+ buffer.append(selectTable_); // @D3A
+ buffer.append(" WHERE CURRENT OF \""); // @D3A
+ buffer.append(cursorName_); // @D3A
+ buffer.append("\""); // @D3A
+ deleteStatement_ = connection_.prepareStatement(buffer.toString()); // @D3C
+ } // @D3A
+
+ deleteStatement_.execute ();
+
+ // Mark the cursor position not valid.
+ positionValid_ = false;
+ rowCache_.flush ();
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // * It seems inefficient to prepare and execute a
+ // new statement each time, but we really have no choice,
+ // since (1.) The combination of columns that we want
+ // to insert could change every time and (2.) We need
+ // to use parameter markers to be able to set columns
+ // not representable using SQL literals.
+ //
+ public void insertRow ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ beforeUpdate ();
+
+ if(positionInsert_ == false)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ // Build up the SQL statement. Make sure a correlation name
+ // is not used.
+ StringBuffer buffer = new StringBuffer ();
+ buffer.append ("INSERT INTO ");
+ buffer.append (selectTable_);
+ buffer.append (" (");
+ StringBuffer values = new StringBuffer ();
+ int columnsSet = 0;
+ for(int i = 0; i < columnCount_; ++i)
+ {
+ if(updateSet_[i] == true)
+ {
+ if(columnsSet++ > 0)
+ {
+ buffer.append (",");
+ values.append (",");
+ }
+ buffer.append ("\""); // @D6a
+ buffer.append (prepareQuotes(row_.getFieldName (i+1))); //@DELIMc
+ buffer.append ("\""); // @D6a
+ values.append ("?");
+ }
+ }
+ if(columnsSet == 0)
+ buffer.append (prepareQuotes(row_.getFieldName (1))); //@DELIMc
+ buffer.append (") VALUES (");
+ if(columnsSet == 0)
+ buffer.append ("NULL");
+ else
+ buffer.append (values.toString()); // added toString() because 1.4 has a method that appends a string buffer
+ buffer.append (")");
+
+ if(JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "Inserting a row: " + buffer);
+
+ // Prepare the statement and set the parameters.
+ PreparedStatement insertStatement = connection_.prepareStatement (buffer.toString ());
+ for(int i = 0, columnsSet2 = 0; i < columnCount_; ++i)
+ {
+ if(updateSet_[i] == true)
+ {
+ Object columnValue = updateRow_.getSQLData (i+1).getObject ();
+ if(updateNulls_[i])
+ insertStatement.setNull (++columnsSet2, row_.getSQLType (i+1).getType ());
+ else if(updateDefaults_[i]) //@EIA
+ ((AS400JDBCPreparedStatement)insertStatement).setDB2Default(++columnsSet2); //@EIA
+ else if(updateUnassigned_[i]) //@EIA
+ ((AS400JDBCPreparedStatement)insertStatement).setDB2Unassigned(++columnsSet2); //@EIA
+ else
+ insertStatement.setObject (++columnsSet2, columnValue);
+ updateSet_[i] = false;
+ }
+ }
+
+ // Execute and close the statement. Dispatch the warnings,
+ // if any.
+ insertStatement.executeUpdate ();
+ SQLWarning warnings = insertStatement.getWarnings ();
+ if(warnings != null)
+ postWarning (warnings); // The whole link gets added.
+ insertStatement.close ();
+
+ rowCache_.flush ();
+ }
+ }
+
+
+ //@DELIMa
+ // Prepares a name to be double-quoted.
+ private final static String prepareQuotes(String name)
+ {
+ return JDUtilities.prepareForDoubleQuotes(name);
+ }
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ // We almost always return false because we don't allow
+ // updates to scroll insensitive or forward only result
+ // sets, so we never have holes.
+ //
+ // The only case where this may be true is if they call
+ // it immediately after deleting a row and then don't
+ // reposition the cursor.
+ return((positionValid_ == false) && (positionInsert_ == false)
+ && ((positionFromFirst_ > 0) || (positionFromLast_ > 0)));
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ // For forward only and scroll insensitive result sets, we don't
+ // have the ability to detect this. For scroll sensitive result
+ // sets, the inserts are visible, but we don't have access to which
+ // were inserted. So we always return false.
+ return false;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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 SQLException
+ {
+ // For forward only and scroll insensitive result sets, we don't
+ // have the ability to detect this. For scroll sensitive result
+ // sets, the inserts are visible, but we don't have access to which
+ // were inserted. So we always return false.
+ return false;
+ }
+
+
+
+ /**
+ Tests if a DataTruncation occurred on the write of a piece of
+ data and posts a DataTruncation warning if so.
+
+ @param columnIndex The column index (1-based).
+ @param data The data that was written, or null for SQL NULL.
+ @since Modification 5
+ **/
+ private void testDataTruncation2 (int columnIndex, SQLData data)
+ throws SQLException // @D5A //@trunc
+ {
+ if(data != null)
+ {
+ int truncated = data.getTruncated ();
+ if(truncated > 0)
+ {
+ int actualSize = data.getActualSize ();
+ throw new DataTruncation (columnIndex, false, false, // @D5C
+ actualSize + truncated, actualSize); // @D5C
+ }
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates the value of a column as an Array object.
+ DB2 for IBM i does not support arrays.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null if the value is SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support arrays.
+ @since Modification 5
+ **/
+ public void updateArray (int columnIndex, Array columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates the value of a column as an Array object.
+ DB2 for IBM i does not support arrays.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateArray("\"MixedCase\"", columnValue).
+
+ @param columnName The column name.
+ @param columnValue The column value or null if the value is SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support arrays.
+ **/
+ public void updateArray (String columnName, Array columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using 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.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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, the
+ requested conversion is not valid,
+ the length is not
+ valid, the input stream does not contain
+ ASCII characters, or an error happens
+ while reading the input stream.
+ **/
+ public void updateAsciiStream (int columnIndex,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex,
+ (columnValue == null) ? null : JDUtilities.streamToString (columnValue, length, "ISO8859_1"), // @B1C
+ null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using 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.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateAsciiStream("\"MixedCase\"", columnValue, length).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, the
+ requested conversion is not valid,
+ the length is not valid,
+ the input stream does not contain
+ ASCII characters, or an error happens
+ while reading the input stream.
+ **/
+ public void updateAsciiStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ updateAsciiStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a BigDecimal value. The
+ driver converts this to an SQL NUMERIC value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, BigDecimal columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex, columnValue, null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a BigDecimal value. The
+ driver converts this to an SQL NUMERIC value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateBigDecimal("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateBigDecimal (String columnName, BigDecimal columnValue)
+ throws SQLException
+ {
+ updateBigDecimal (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using 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.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 updateBinaryStream (int columnIndex,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex,
+ (columnValue == null) ? null : JDUtilities.streamToBytes (columnValue, length), // @B1C
+ null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using 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.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateBinaryStream("\"MixedCase\"", columnValue, length).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid,
+ the length is not valid, or an error
+ happens while reading the input stream.
+ **/
+ public void updateBinaryStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ updateBinaryStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java boolean value.
+ The driver converts this to an SQL SMALLINT value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // The spec defines this in terms of SQL BIT, but DB2 for IBM i
+ // does not support that.
+ //
+ public void updateBoolean (int columnIndex, boolean columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Short ((short) (columnValue ? 1 : 0)), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java boolean value.
+ The driver converts this to an SQL SMALLINT value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateBoolean("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ @since Modification 5
+ **/
+ //
+ // Implementation note:
+ //
+ // The spec defines this in terms of SQL BIT, but DB2 for IBM i
+ // does not support that.
+ //
+ public void updateBoolean (String columnName, boolean columnValue)
+ throws SQLException
+ {
+ updateBoolean (findColumn (columnName), columnValue);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Blob value.
+ The driver converts this to an SQL BLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ @since Modification 5
+ **/
+ public void updateBlob (int columnIndex, Blob columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, columnValue, null, -1);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Blob value.
+ The driver converts this to an SQL BLOB value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateBlob("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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, Blob columnValue)
+ throws SQLException
+ {
+ updateValue (findColumn (columnName), columnValue, null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java byte value.
+ The driver converts this to an SQL SMALLINT value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // The spec defines this in terms of SQL TINYINT, but DB2 for IBM i
+ // does not support that.
+ //
+ public void updateByte (int columnIndex, byte columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Short (columnValue), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java byte value.
+ The driver converts this to an SQL SMALLINT value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateByte("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // The spec defines this in terms of SQL TINYINT, but DB2 for IBM i
+ // does not support that.
+ //
+ public void updateByte (String columnName, byte columnValue)
+ throws SQLException
+ {
+ updateByte (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java byte array value.
+ The driver converts this to an SQL VARBINARY value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, byte[] columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex, columnValue, null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java byte array value.
+ The driver converts this to an SQL VARBINARY value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateBytes("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateBytes (String columnName, byte[] columnValue)
+ throws SQLException
+ {
+ updateBytes (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex,
+ (columnValue == null) ? null : JDUtilities.readerToString (columnValue, length), // @B1C
+ null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateCharacterStream("\"MixedCase\"", columnValue, length).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid,
+ the length is not valid, or an error
+ happens while reading the input stream.
+ @since Modification 5
+ **/
+ public void updateCharacterStream (String columnName,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ updateCharacterStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Clob value.
+ The driver converts this to an SQL CLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ @since Modification 5
+ **/
+ public void updateClob (int columnIndex, Clob columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, columnValue, null, -1);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Clob value.
+ The driver converts this to an SQL CLOB value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateClob("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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, Clob columnValue)
+ throws SQLException
+ {
+ updateValue (findColumn (columnName), columnValue, null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Date value.
+ The driver converts this to an SQL DATE value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, Date columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex, columnValue, null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Date value.
+ The driver converts this to an SQL DATE value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateDate("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateDate (String columnName, Date columnValue)
+ throws SQLException
+ {
+ updateDate (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java double value.
+ The driver converts this to an SQL DOUBLE value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, double columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Double (columnValue), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java double value.
+ The driver converts this to an SQL DOUBLE value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateDouble("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateDouble (String columnName, double columnValue)
+ throws SQLException
+ {
+ updateDouble (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java float value.
+ The driver converts this to an SQL REAL value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, float columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Float (columnValue), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java float value.
+ The driver converts this to an SQL REAL value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateFloat("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateFloat (String columnName, float columnValue)
+ throws SQLException
+ {
+ updateFloat (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java int value.
+ The driver converts this to an SQL INTEGER value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, int columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Integer (columnValue), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java int value.
+ The driver converts this to an SQL INTEGER value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateInt("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateInt (String columnName, int columnValue)
+ throws SQLException
+ {
+ updateInt (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ // @D0C
+ /**
+ Updates a column in the current row using 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.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // The spec defines this in terms of SQL BIGINT, but DB2 for IBM i
+ // does not support that until V4R5.
+ //
+ public void updateLong (int columnIndex, long columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Long(columnValue), null, -1); // @D0C
+ }
+
+
+
+ // JDBC 2.0
+ // @D0C
+ /**
+ Updates a column in the current row using 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.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateLong("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, 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 void updateLong (String columnName, long columnValue)
+ throws SQLException
+ {
+ updateLong (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using SQL NULL.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex 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 columnIndex)
+ throws SQLException
+ {
+ updateValue (columnIndex, null, null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using SQL NULL.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateNull("\"MixedCase\"").
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateNull (String columnName)
+ throws SQLException
+ {
+ updateNull (findColumn (columnName));
+ }
+
+
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Default.
+ @param columnIndex The column index (1-based).
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDB2Default(int columnIndex) throws SQLException
+ {
+ updateValueExtendedIndicator (columnIndex, 1); //1 is default
+ }
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Default. Same as updateDB2Default.
+ @param columnIndex The column index (1-based).
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDBDefault(int columnIndex) throws SQLException
+ {
+ updateDB2Default(columnIndex);
+ }
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Default.
+ @param columnName The column name.
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDB2Default(String columnName) throws SQLException
+ {
+ updateDB2Default (findColumn (columnName));
+ }
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Default. Same as updateDB2Default.
+ @param columnName The column name.
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDBDefault(String columnName) throws SQLException
+ {
+ updateDB2Default (findColumn (columnName));
+ }
+
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Unassigned.
+ @param columnIndex The column index (1-based).
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDB2Unassigned(int columnIndex) throws SQLException
+ {
+ updateValueExtendedIndicator (columnIndex, 2); //2 is unassigned
+ }
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Unassigned. Same as updtaeDB2Unassigned.
+ @param columnIndex The column index (1-based).
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDBUnassigned(int columnIndex) throws SQLException
+ {
+ updateDB2Unassigned(columnIndex);
+ }
+
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Unassigned.
+ @param columnName The column name.
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDB2Unassigned(String columnName) throws SQLException
+ {
+ updateDB2Unassigned (findColumn (columnName));
+ }
+
+
+ //@EIA 550 extended indicator defaults
+ /**
+ Updates a column in the current row to the SQL Unassigned. Same as updateDB2Unassigned.
+ @param columnName The column name.
+ @exception SQLException If the statement is not open,
+ the index is not valid, the parameter
+ is not an input parameter.
+ **/
+ public void updateDBUnassigned(String columnName) throws SQLException
+ {
+ updateDB2Unassigned (findColumn (columnName));
+ }
+
+
+ // JDBC 2.0
+ /**
+ 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. In the cases
+ where an SQL type is not supported by DB2 for IBM i, the
+ next closest matching type
+ is used.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, Object columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+
+ updateValue (columnIndex, columnValue, null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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. In the cases
+ where an SQL type is not supported by DB2 for IBM i, the
+ next closest matching type
+ is used.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateObject("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found,
+ or the requested conversion is not valid.
+ **/
+ public void updateObject (String columnName, Object columnValue)
+ throws SQLException
+ {
+ updateObject (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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. In the cases
+ where an SQL type is not supported by DB2 for IBM i, the
+ next closest matching type
+ is used.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+ @param scale The number of digits after the decimal
+ if SQL type is DECIMAL or NUMERIC.
+
+ @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,
+ the scale is not valid, or the
+ requested conversion is not valid.
+ **/
+ public void updateObject (int columnIndex,
+ Object columnValue,
+ int scale)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+
+ if(scale < 0)
+ JDError.throwSQLException (JDError.EXC_SCALE_INVALID);
+
+/* ifdef JDBC40 */
+ if (columnValue instanceof SQLXML) //@xmlspec
+ updateSQLXML(columnIndex, (SQLXML)columnValue); //@xmlspec
+ else
+/* endif */
+ updateValue (columnIndex, columnValue, null, scale); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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. In the cases
+ where an SQL type is not supported by DB2 for IBM i, the
+ next closest matching type
+ is used.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateObject("\"MixedCase\"", columnValue, scale).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+ @param scale The number of digits after the decimal
+ if SQL type is DECIMAL or NUMERIC.
+
+ @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 name is not found,
+ the scale is not valid, or the
+ requested conversion is not valid.
+ @since Modification 5
+ **/
+ public void updateObject (String columnName,
+ Object columnValue,
+ int scale)
+ throws SQLException
+ {
+ updateObject (findColumn (columnName), columnValue, scale);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates the value of an SQL REF output parameter as a Ref value.
+ DB2 for IBM i does not support structured types.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support REFs.
+ @since Modification 5
+ **/
+ public void updateRef (int columnIndex, Ref columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates the value of an SQL REF output parameter as a Ref value.
+ DB2 for IBM i does not support structured types.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateRef("\"MixedCase\"", columnValue).
+
+ @param columnName The column name.
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support REFs.
+ **/
+ public void updateRef (String columnName, Ref columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates the database with the new contents of the current
+ row.
+
+ @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.
+ **/
+ //
+ // Implementation note:
+ //
+ // * It seems inefficient to prepare and execute a
+ // new statement each time, but we really have no choice,
+ // since (1.) The combination of columns that we want
+ // to update could change every time and (2.) We need
+ // to use parameter markers to be able to set columns
+ // not representable using SQL literals.
+ //
+ public void updateRow ()
+ throws SQLException
+ {
+ beforeUpdate ();
+ DBExtendedColumnDescriptors extendedDescriptors = null; //@K1A
+ ConvTable convTable = null; //@K1A
+
+ if((positionInsert_ == true) || (positionValid_ == false))
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ // Build up the SQL statement.
+ StringBuffer buffer = new StringBuffer ();
+ buffer.append ("UPDATE ");
+ buffer.append (selectTable_);
+ if(correlationName_ != null)
+ {
+ buffer.append (" AS ");
+ buffer.append (correlationName_);
+ }
+ buffer.append (" SET ");
+ int columnsSet = 0;
+ for(int i = 0; i < columnCount_; ++i)
+ {
+ if(updateSet_[i] == true)
+ {
+ if(columnsSet++ > 0)
+ buffer.append (",");
+ buffer.append ("\""); // @D6a
+ // @K1A If we have column descriptors, use them to get the column label. //@K1A
+ if(statement_ != null) //@K1A
+ {
+ // @K1A
+ extendedDescriptors = statement_.getExtendedColumnDescriptors(); // @K1A
+ // If we have extendedDescriptors, send a ConvTable to convert them, else pass null // @K1A
+ if(extendedDescriptors != null) // @K1A
+ {
+ // @K1A
+ convTable = ((AS400JDBCConnection)connection_).converter_; // @K1A
+ String columnName = extendedDescriptors.getColumnDescriptors(i+1, convTable).getBaseColumnName(convTable); //@K1A //@K2A changed from getColumnLabel //@SS1
+ if(columnName != null) {
+ if (((AS400JDBCConnection)connection_).getVRM() < JDUtilities.vrm540) { //@DELIMa
+ buffer.append(JDUtilities.stripOuterDoubleQuotes(columnName)); // if pre-V5R4, just strip outer quotes (no double-up necessary)
+ }
+ else {
+ buffer.append(prepareQuotes(columnName)); // if V5R4+, also need to double-up any embedded quotes @DELIMc
+ }
+ }
+ else { // Column name is null, so get it from the row.
+ // We're using extended descriptors,
+ // so we'll need to double-up embedded quotes.
+ buffer.append(prepareQuotes(row_.getFieldName(i+1))); //@DELIMa
+ }
+ } // @K1A
+ else // @K1A
+ buffer.append (prepareQuotes(row_.getFieldName (i+1))); // @K1A @DELIMc
+ // @K1A
+ }
+ else
+ buffer.append(prepareQuotes(row_.getFieldName(i+1)));
+ buffer.append ("\"=?"); // @D6c @DELIMc
+ }
+ }
+ buffer.append (" WHERE CURRENT OF \""); // @D3C
+ buffer.append (cursorName_);
+ buffer.append ("\""); // @D3C
+
+ // Only go through with this if columns were set.
+ if(columnsSet > 0)
+ {
+
+ if(JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "Updating a row: " + buffer);
+
+ // Prepare the statement and set the parameters.
+ PreparedStatement updateStatement = connection_.prepareStatement (buffer.toString ());
+ try{
+ for(int i = 0, columnsSet2 = 0; i < columnCount_; ++i)
+ {
+ if(updateSet_[i] == true)
+ {
+ Object columnValue = updateRow_.getSQLData (i+1).getObject ();
+ if(updateNulls_[i] == true)
+ updateStatement.setNull (++columnsSet2, row_.getSQLType (i+1).getType ());
+ else if(updateDefaults_[i]) //@EIA
+ ((AS400JDBCPreparedStatement)updateStatement).setDB2Default(++columnsSet2); //@EIA
+ else if(updateUnassigned_[i]) //@EIA
+ ((AS400JDBCPreparedStatement)updateStatement).setDB2Unassigned(++columnsSet2); //@EIA
+ else
+ updateStatement.setObject (++columnsSet2, columnValue);
+ }
+ }
+
+ // Execute and close the statement. Dispatch the warnings,
+ // if any.
+ updateStatement.executeUpdate ();
+ SQLWarning warnings = updateStatement.getWarnings ();
+ if(warnings != null)
+ postWarning (warnings); // The whole link gets added.
+ }
+ finally{
+ //Always close the statement - Fix for JTOpen Bug 4148
+ updateStatement.close ();
+ }
+
+ rowCache_.flush ();
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java short value.
+ The driver converts this to an SQL SMALLINT value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, short columnValue)
+ throws SQLException
+ {
+ updateValue (columnIndex, new Short (columnValue), null, -1);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a Java short value.
+ The driver converts this to an SQL SMALLINT value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateShort("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateShort (String columnName, short columnValue)
+ throws SQLException
+ {
+ updateShort (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a String value.
+ The driver converts this to an SQL VARCHAR value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, String columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+
+ //if(columnIndex <= columnCount_ && columnIndex > 0) //@pdc
+ // columnValue = AS400BidiTransform.convertDataToHostCCSID(columnValue, (AS400JDBCConnection) connection_, ((JDServerRow) row_).getCCSID(columnIndex)); //Bidi-HCG
+
+ updateValue (columnIndex, columnValue, null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a String value.
+ The driver converts this to an SQL VARCHAR value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateString("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateString (String columnName, String columnValue)
+ throws SQLException
+ {
+ updateString (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Time value.
+ The driver converts this to an SQL TIME value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, Time columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex, columnValue, null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Time value.
+ The driver converts this to an SQL TIME value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateTime("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateTime (String columnName, Time columnValue)
+ throws SQLException
+ {
+ updateTime (findColumn (columnName), columnValue);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Timestamp value.
+ The driver converts this to an SQL TIMESTAMP value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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 columnIndex, Timestamp columnValue)
+ throws SQLException
+ {
+ // @B1D if (columnValue == null)
+ // @B1D JDError.throwSQLException (JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ updateValue (columnIndex, columnValue, null, -1); //@P0C
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Updates a column in the current row using a java.sql.Timestamp value.
+ The driver converts this to an SQL TIMESTAMP value.
+ To perform a case-sensitive search use a quoted String
+ for columnName as in: ResultSet.updateTimestamp("\"MixedCase\"", columnValue).
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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 name is not found, or the
+ requested conversion is not valid.
+ **/
+ public void updateTimestamp (String columnName, Timestamp columnValue)
+ throws SQLException
+ {
+ updateTimestamp (findColumn (columnName), columnValue);
+ }
+
+
+
+ /**
+ Updates a column for the specified index, and performs all
+ appropriate validation.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null if the value
+ is SQL NULL.
+ @param calendar The calendar, or null if not
+ applicable.
+ @param scale The scale, or -1 if not applicable.
+
+ @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.
+ **/
+ private void updateValue(int columnIndex, Object columnValue,
+ Calendar calendar, int scale) throws SQLException {
+ synchronized (internalLock_) { // @D1A
+ beforeUpdate();
+
+ // Check that there is a current row.
+ if ((positionValid_ == false) && (positionInsert_ == false))
+ JDError.throwSQLException(JDError.EXC_CURSOR_POSITION_INVALID);
+
+ // Validate The column index.
+ if ((columnIndex < 1) || (columnIndex > columnCount_))
+ JDError.throwSQLException(JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Set the update value. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = updateRow_.getSQLType(columnIndex); // @P0C
+ int columnIndex0 = columnIndex - 1;
+
+ // @G7A If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (columnValue != null
+ && (sqlType == SQLData.CLOB_LOCATOR
+ || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR
+ || sqlType == SQLData.NCLOB_LOCATOR || // @pda jdbc40
+ sqlType == SQLData.XML_LOCATOR)) // @xml3
+ {
+ // @G8C //@G7A
+ // @J5A Restructured to use instanceof to avoid ClassCastException
+ if (columnValue instanceof AS400JDBCBlobLocator) { // @J5A
+ try { // @G7A
+ statement_.setAssociatedWithLocators(true); // @KBL
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData; // @G7A
+ sqlDataAsLocator.setHandle(((AS400JDBCBlobLocator) columnValue)
+ .getHandle()); // @G7A
+ } // @G7A
+ catch (ClassCastException cce) // @G7A
+ {
+ /* ignore */// @G7A
+ } // @G7A
+ } else if (columnValue instanceof AS400JDBCClobLocator) { // @J5A
+ try { // @G7A
+ statement_.setAssociatedWithLocators(true); // @KBL
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData; // @G7A
+ sqlDataAsLocator.setHandle(((AS400JDBCClobLocator) columnValue)
+ .getHandle()); // @G7A
+ } // @G7A
+ catch (ClassCastException cce) // @G7A
+ {
+ /* ignore */
+ } // @G7A
+ } else if (columnValue instanceof AS400JDBCNClobLocator) { // @J5A
+ try // @PDA jdbc40 - following upon existing design
+ { // @PDA jdbc40
+ statement_.setAssociatedWithLocators(true); // @KBL
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData; // @PDA jdbc40
+ sqlDataAsLocator.setHandle(((AS400JDBCNClobLocator) columnValue)
+ .getHandle()); // @PDA jdbc40
+ } // @PDA jdbc40
+ catch (ClassCastException cce) // @PDA jdbc40
+ {
+ // ignore
+ }
+ } else if (columnValue instanceof AS400JDBCSQLXMLLocator) { // @J5A
+ try // @olddesc
+ { // @olddesc
+ statement_.setAssociatedWithLocators(true); // @KBL
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData; // @olddesc
+ sqlDataAsLocator.setHandle(((AS400JDBCSQLXMLLocator) columnValue)
+ .getHandle()); // @olddesc
+ } // @olddesc
+ catch (ClassCastException cce) // @olddesc
+ {
+ // ignore
+ }
+ }
+ }
+
+ if (columnValue != null)
+ sqlData.set(columnValue, calendar, scale);
+ updateNulls_[columnIndex0] = (columnValue == null);
+ updateDefaults_[columnIndex0] = false; // @EIA
+ updateUnassigned_[columnIndex0] = false; // @EIA
+ updateSet_[columnIndex0] = true;
+
+ if (dataTruncation_) // @B2A
+ testDataTruncation2(columnIndex, sqlData); // @B2C
+ }
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Retrieves the holdability of this Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * At a minimum, an implementation must support the conversions defined in Appendix B, Table B-3 and
+ * conversion of appropriate user defined SQL types to a Java type which implements SQLData,
+ * or Struct. Additional conversions may be supported and are vendor defined.
+ *
+ * @param columnIndex - the first column is 1, the second is 2, ...
+ * @param type - Class representing the Java data type to convert the designated column to.
+ * @returns an instance of type holding the column value
+ * @exception SQLException - if conversion is not supported, type is null or another error occurs.
+ * The getCause() method of the exception may provide a more detailed exception, for example, if a conversion error occurs
+ * @exception SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+ */
+
+/*
+ public At a minimum, an implementation must support the conversions defined in Appendix B, Table B-3 and conversion of
+ * appropriate user defined SQL types to a Java type which implements SQLData, or Struct. Additional conversions may be
+ * supported and are vendor defined.
+ *@param columnLabel - the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ *@param type - Class representing the Java data type to convert the designated column to.
+ *@return an instance of type holding the column value
+ *@exception SQLException - if conversion is not supported, type is null or another error occurs. The getCause() method of the exception may provide a more detailed exception, for example, if a conversion error occurs
+ *@exception SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+ */
+
+/*
+ public The AS400JDBCResultSetMetaData class describes the
+columns in a result set.
+**/
+//
+// Implementation notes:
+//
+// * I lifted the restriction that a result set be open when
+// using this object, specifically so it could be used after
+// preparing but before executing (via PreparedStatement.getMetaData()).
+//
+// * I also removed the reference to the result set as private
+// data. This is again because of the need to create this object
+// before executing a query (via PreparedStatement.getMetaData()).
+//
+public class AS400JDBCResultSetMetaData
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+implements ResultSetMetaData
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+ // Private static final ints
+ // Searchable constants
+ //@G1A @G2C
+ static final int SQL_UNSEARCHABLE = 0xF0; // isSearchable = false
+ static final int SQL_LIKE_ONLY = 0xF1; // will not be returned by our IBM i system
+ static final int SQL_ALL_EXCEPT_LIKE = 0xF2; // isSearchable = true
+ static final int SQL_SEARCHABLE = 0xF3; // isSearchable = true
+
+ // Updateable constants
+ //@G1A @G2C
+ static final int SQL_READ_ONLY = 0xF0; // isReadOnly = true, isWriteable = false
+ static final int SQL_WRITE_CAPABLE = 0xF1; // isReadOnly = false, isWriteable = true
+ static final int SQL_READ_WRITE_UNKNOWN = 0xF2; // will not be returned by our IBM i system
+
+ // Private data.
+ private String catalog_;
+ private int concurrency_;
+ private String cursorName_;
+ private JDRow row_;
+ private DBExtendedColumnDescriptors extendedColumnDescriptors_; //@G1A
+ private ConvTable convTable_; //@G1A
+ private Connection con_; //@in1
+
+ /**
+ Constructs an AS400JDBCResultSetMetaData object.
+ @param catalog The catalog.
+ @param concurrency The result set concurrency.
+ @param cursorName The cursor name.
+ @param row The row.
+ @param extendedColumnDescriptors The extended column descriptors.
+ @param convTable The converter table to use to convert column descriptors.
+ **/
+ AS400JDBCResultSetMetaData(String catalog,
+ int concurrency,
+ String cursorName,
+ JDRow row,
+ DBExtendedColumnDescriptors extendedColumnDescriptors, //@G1A
+ ConvTable convTable, //@G1A
+ Connection con) //@in1
+ {
+ catalog_ = catalog;
+ concurrency_ = concurrency;
+ cursorName_ = cursorName;
+ row_ = row;
+ extendedColumnDescriptors_ = extendedColumnDescriptors; //@G1A
+ convTable_ = convTable; //@G1A
+ con_ = con; //@in1
+ }
+
+ /**
+ Throws an exception if the specified column index is not
+ valid.
+ @param columnIndex The column index (1-based).
+ @exception SQLException If the column index is not valid.
+ **/
+ private void checkIndex(int columnIndex)
+ throws SQLException
+ {
+ // Validate the column index.
+ if((columnIndex < 1) || (columnIndex > row_.getFieldCount()))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+
+ /**
+ Returns the catalog name of the table for a column.
+ @param columnIndex The column index (1-based).
+ @return The catalog name.
+ @exception SQLException If the column index is not valid.
+ **/
+ public String getCatalogName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return catalog_;
+ }
+
+ // JDBC 2.0
+ /**
+ Returns the name of a Java class whose instances are
+ created if ResultSet.getObject() is called to retrieve
+ from the column. The actual class created may be a subclass
+ of the returned class.
+ @param columnIndex The column index (1-based).
+ @return The class name.
+ @exception SQLException If the column index is not valid.
+ **/
+ //
+ // Implementation note:
+ //
+ // * In the case where the column returns a byte array, this
+ // returns "[B". See the javadoc for java.lang.Class.getName()
+ // for the reason why. The JDBC 2.0 specification does not
+ // really go into detail, so it is unclear if this is okay
+ // to return. I will assume so in the mean time.
+ //
+ public String getColumnClassName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ SQLData sqlData = row_.getSQLType(columnIndex);
+ String className = sqlData.getObject().getClass().getName();
+ return className;
+ }
+
+ /**
+ Returns the number of columns in the result set.
+ @return The number of columns.
+ @exception SQLException If an error occurs.
+ **/
+ public int getColumnCount()
+ throws SQLException
+ {
+ return row_.getFieldCount();
+ }
+
+ /**
+ Returns the normal maximum width of a column.
+ @param columnIndex The column index (1-based).
+ @return The normal maximum width
+ (in characters).
+ @exception SQLException If the column index is not valid.
+ **/
+ public int getColumnDisplaySize(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.getSQLType(columnIndex).getDisplaySize();
+ }
+
+ /**
+ Returns the suggested label for use in printouts
+ or displays for a column.
+ @param columnIndex The column index (1-based).
+ @return The column label if the user set the
+ driver property "extended metadata" to true and
+ the system returns us a column label,
+ otherwise the column name.
+ @exception SQLException If the column index is not valid.
+ **/
+ //
+ // Implementation note:
+ //
+ // For now, this is the same as the field name. In
+ // order to get the field label, we would have to make
+ // an extra request to the ROI server and perform a lot
+ // of extra processing. This performance hit is not
+ // worth it. If the caller really needs the label, then
+ // they can use DatabaseMetaData.getColumns.
+ //
+ // As of mod5 of Toolbox, we can use extended column descriptors
+ // (if the user asked for the by setting the "extended metadata" property
+ // to true) which will flow back to us without an extra call to the ROI server.
+ //
+ public String getColumnLabel(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ // @G1A If we have column descriptors, use them to get the column label. //@G1A
+ if(extendedColumnDescriptors_ != null) //@G1A
+ {
+ //@G1A
+ DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_); //@KBA // Fix for JTOpen Bug 4034 The ccsid for the column may be 65535, if that is the case, we want to use the job's ccsid
+ if(dataFormat != null) //@KBA The data format returned by the host server will be null for columns created by expressions, use old way
+ { //@D9A
+ String columnLabel = dataFormat.getColumnLabel(convTable_); //@D9A
+ if(columnLabel != null) //@D9A
+ return columnLabel; //@D9A
+ //@D9D return dataFormat.getColumnLabel(convTable_); //@KBA
+ //@KBD return extendedColumnDescriptors_.getColumnDescriptors(columnIndex).getColumnLabel(convTable_); //@G1A
+ }
+ } //@G1A
+
+ //else use the "old way".
+ return row_.getFieldName(columnIndex);
+ }
+
+ /**
+ Returns the name of a column.
+ @param columnIndex The column index (1-based).
+ @return The column name.
+ @exception SQLException If the column index is not valid.
+ **/
+ public String getColumnName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ String columnName =row_.getFieldName(columnIndex);
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getColumnName("+columnIndex+") returned " + columnName);
+ }
+ return columnName;
+ }
+
+ /**
+ Returns the type of a column. If the type is a distinct type,
+ this returns the underlying type.
+ @param columnIndex The column index (1-based).
+ @return The SQL type code defined in java.sql.Types.
+ @exception SQLException If the column index is not valid.
+ **/
+ public int getColumnType(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.getSQLType(columnIndex).getType();
+ }
+
+ /**
+ Returns the type name of a column. If the type is a distinct
+ type, this returns the underlying type name.
+ @param columnIndex The column index (1-based).
+ @return The column type name.
+ @exception SQLException If the column index is not valid.
+ **/
+ public String getColumnTypeName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.getSQLType(columnIndex).getTypeName();
+ }
+
+ /**
+ Returns the precision of a column. This is the number
+ of decimal digits the column may hold.
+ @param columnIndex The column index (1-based).
+ @return The precision.
+ @exception SQLException If the column index is not valid.
+ **/
+ public int getPrecision(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.getSQLType(columnIndex).getPrecision();
+ }
+
+ /**
+ Returns the scale of a column. This is number of digits
+ to the right of the decimal point.
+ @param columnIndex The column index (1-based).
+ @return The scale.
+ @exception SQLException If the column index is not valid.
+ **/
+ public int getScale(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.getSQLType(columnIndex).getScale();
+ }
+
+ /**
+ Returns the schema name of the table for a column.
+ This method is supported only if the user has set the
+ driver property "extended metadata" to true.
+ @param columnIndex The column index (1-based).
+ @return The schema name if the user set the
+ driver property "extended metadata" to true and
+ the system returns us a schema name,
+ otherwise "".
+ @exception SQLException If the column index is not valid.
+ **/
+ public String getSchemaName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+
+ // @G1A If we have column descriptors, use them to get the schema name. //@G1A
+ if(extendedColumnDescriptors_ != null) //@G1A
+ {
+ //@G1A
+ DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_); //@KBA //@ss1
+ if(dataFormat != null) //@KBA Depending on the query, dataFormat returned by the host server may be null. For example, if a union was used or an expression
+ return dataFormat.getBaseTableSchemaName(convTable_); //@G1A
+ } //@G1A
+
+ //else return ""
+ return "";
+ }
+
+ /**
+ Returns the column's table name.
+ This method is supported only if the user has set the
+ driver property "extended metadata" to true.
+ @param columnIndex The column index (1-based).
+ @return The base table name if the user set the
+ driver property "extended metadata" to true and
+ the system returns us a table name,
+ otherwise "".
+ @exception SQLException If the column index is not valid.
+ **/
+ public String getTableName(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+
+ // Changed to get the Base Table Name for a column if the extended metadata property is true
+ // because we already have the information, we should return it to the user if they want it...
+ if(extendedColumnDescriptors_ != null)
+ {
+ DBColumnDescriptorsDataFormat dataFormat = extendedColumnDescriptors_.getColumnDescriptors(columnIndex, convTable_); //@KBA //@ss1
+ if(dataFormat != null) //@KBA Depending on the query, dataFormat returned by the host server may be null. For example, if a union was used or an expression
+ return dataFormat.getBaseTableName(convTable_); //@KBA
+ //@KBD return extendedColumnDescriptors_.getColumnDescriptors(columnIndex).getBaseTableName(convTable_); //K1C use to call getBaseTableSchemaName
+ }
+
+ // we still return "" if we don't have the Base Table Name
+ return "";
+ }
+
+ /**
+ Indicates if the column is automatically numbered.
+ @param columnIndex The column index (1-based).
+ @return True if column is autoincrement, false otherwise.
+ @exception SQLException If the column index is not valid.
+ Note: connection property "extended metadata" must be true for this method to be return accurate information.
+ If the "extended metadata" connection property is not set to true, then this method will always return false.
+ **/
+ public boolean isAutoIncrement(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+
+ // Only run the query to get the information if the table name can be found. The table name
+ // can only be found if "extended metadata" == true
+ // @A9A
+
+ String tableName = this.getTableName(columnIndex);
+ if ((tableName == null) || (tableName.length() == 0) ) {
+ return false;
+ }
+
+ //return false; //@in1 add implementation instead of always returning false
+
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ try
+ {
+ ps = con_.prepareStatement("SELECT identity_generation " +
+ "FROM QSYS2" + getCatalogSeparator() + "SYSCOLUMNS" +
+ " WHERE identity_generation is not null" +
+ " AND column_name = ?" +
+ " AND table_name = ?" +
+ " AND table_schema = ?");
+ ps.setString(1, this.getColumnName(columnIndex));
+ ps.setString(2, tableName);
+ ps.setString(3, this.getSchemaName(columnIndex));
+
+ rs = ps.executeQuery();
+ if ( rs.next())
+ return true;
+ else
+ return false;
+
+ }
+ catch (SQLException e)
+ {
+ throw e;
+ }
+ finally
+ {
+ try{
+ if(rs != null)
+ rs.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "isAutoIncrement rs.close()", e);
+ } //allow next close to execute
+ if(ps != null)
+ ps.close();
+ }
+ }
+
+ /**
+ Indicates if the column is case sensitive.
+ @param columnIndex The column index (1-based).
+ @return true if the column is case sensitive;
+ false otherwise.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isCaseSensitive(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+
+ // In DB2 for IBM i, all text types
+ // are case sensitive.
+ return row_.getSQLType(columnIndex).isText();
+ }
+
+ /**
+ Indicates if the column is a currency value.
+ @param columnIndex The column index (1-based).
+ @return Always false. DB2 for IBM i
+ does not directly support currency
+ values.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isCurrency(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return false;
+ }
+
+ /**
+ Indicates if a write on the column will definitely succeed.
+ @param columnIndex The column index (1-based).
+ @return Always false. The driver does
+ not check if the user has the
+ necessary authority to write to
+ the column.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isDefinitelyWritable(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return false;
+ }
+
+ /**
+ Indicates if the column can contain an SQL NULL value.
+ @param columnIndex The column index (1-based).
+ @return true if the column is can contain
+ an SQL NULL value; false otherwise.
+ @exception SQLException If the column index is not valid.
+ **/
+ public int isNullable(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return row_.isNullable(columnIndex);
+ }
+
+ /**
+ Indicates if the column is read-only.
+ @param columnIndex The column index (1-based).
+ @return true if the column is read-only;
+ false otherwise.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isReadOnly(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+
+ // @G1A If we have column descriptors, use them to get searchable label. //@G1A
+ if(extendedColumnDescriptors_ != null)// && concurrency_ != ResultSet.CONCUR_READ_ONLY) //@G1A @G3C @36072
+ {
+ //@G1A
+ if(extendedColumnDescriptors_.getUpdateable(columnIndex) == (byte)SQL_READ_ONLY) //@G1A @G2C
+ return true; //@G1A
+ else //@G1A
+ return false; //@G1A
+ } //@G1A
+
+ // else use "old" way
+ return(concurrency_ == ResultSet.CONCUR_READ_ONLY);
+ }
+
+ /**
+ Indicates if the column be used in a where clause.
+ @param columnIndex The column index (1-based).
+ @return If the user has set the "extended metadata" driver property to true,
+ returns true if the column can be used in a where clause
+ with any comparison operator except LIKE, returns
+ false if the column cannot be used in a where clause.
+ If the "extended metadata" driver property is set to false,
+ true will always be returned.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isSearchable(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ // @G1A If we have column descriptors, use them to get searchable label. //@G1A
+ if(extendedColumnDescriptors_ != null) //@G1A
+ {
+ //@G1A
+ if(extendedColumnDescriptors_.getSearchable(columnIndex) == (byte)SQL_UNSEARCHABLE) //@G1A @G2C
+ return false; //@G1A
+ else //@G1A
+ return true; //@G1A
+ } //@G1A
+
+ // Else, return true
+ return true;
+ }
+
+ /**
+ Indicates if the column can contain a signed value.
+ @param columnIndex The column index (1-based).
+ @return true if the column is signed;
+ false otherwise.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isSigned(int columnIndex)
+ throws SQLException
+ {
+ checkIndex(columnIndex);
+ return(row_.getSQLType(columnIndex).isSigned());
+ }
+
+ /**
+ Indicates if it is possible for a write on the column to succeed.
+ The write may fail even if this method returns true.
+ The accuracy of this method will be improved if the "extended metadata"
+ property is set to true.
+ @param columnIndex The column index (1-based).
+ @return true if it is possible for a write on
+ the column to succeed; false otherwise.
+ @exception SQLException If the column index is not valid.
+ **/
+ public boolean isWritable(int columnIndex)
+ throws SQLException
+ {
+ //@G1D checkIndex (columnIndex);
+ //@G1D return(concurrency_ != ResultSet.CONCUR_READ_ONLY);
+ return !isReadOnly(columnIndex); //@G1A
+ }
+
+ /**
+ Returns the name of the SQL cursor in use by this result set.
+ @return The cursor name.
+ **/
+ public String toString()
+ {
+ return cursorName_;
+ }
+
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCResultSetMetaData", "java.sql.ResultSetMetaData" };
+ }
+
+ //@in1 (copied from AS400JDBCDatabaseMetadata)
+ /**
+ Returns the naming convention used when referring to tables.
+ This depends on the naming convention specified in the connection
+ properties.
+
+ @return If using SQL naming convention, "." is returned. If
+ using system naming convention, "/" is returned.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ private String getCatalogSeparator ()
+ throws SQLException
+ {
+ String catalogSeparator;
+ if (((AS400JDBCConnection)con_).getProperties().equals (JDProperties.NAMING, JDProperties.NAMING_SQL))
+ catalogSeparator = ".";
+ else
+ catalogSeparator = "/";
+
+ return catalogSeparator;
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCRowId.java b/jdbc40/com/ibm/as400/access/AS400JDBCRowId.java
new file mode 100644
index 000000000..432f4074f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCRowId.java
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCRowId.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+
+//@PDA jdbc40 new class
+public class AS400JDBCRowId
+/* ifdef JDBC40 */
+implements RowId
+/* endif */
+{
+
+ private byte[] data_;
+ //put byteToHex conversion here in case BinaryConverter is not in jar.
+ private static final char[] c_ = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+
+ /**
+ * Constructs an AS400JDBCRowId object. The data is contained
+ * in the raw byte array. No further communication with the IBM i system
+ * is necessary.
+ *
+ * @param data The RowId data.
+ **/
+ AS400JDBCRowId(byte[] data)
+ {
+ data_ = data;
+ }
+
+ /**
+ * Compares this
+ * It is important
+ * to consider both the origin and the valid lifetime of a
+ * Like
+* Either the url or dataSourceName property must be set to specify how the database connection
+* is established. The command property must be set to specify how to create the PreparedStatement.
+*
+* This example creates an AS400JDBCRowSet object, populates it, and then updates its contents.
+* This example creates an AS400JDBCRowSet object, sets the data source and command parameters and then
+* populates it.
+*
+* AS400JDBCRowSet objects generate the following events:
+* 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.
+ *
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @param rowNumber The absolute row number (1-based). 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 rowNumber) throws SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.absolute(rowNumber);
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+ /**
+ * Adds a PropertyChangeListener.
+ * @param listener The PropertyChangeListener.
+ * @see #removePropertyChangeListener
+ **/
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (listener == null)
+ throw new NullPointerException("listener");
+ changes_.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Adds a RowSetListener to the list.
+ * @param listener The RowSetListener object.
+ **/
+ public void addRowSetListener(RowSetListener listener)
+ {
+ eventSupport_.addRowSetListener(listener);
+ }
+
+ /**
+ * Positions the cursor after the last row.
+ * If an InputStream from the current row is open, it is implicitly closed.
+ * In addition, all warnings and pending updates are cleared.
+ *
+ * @exception SQLException If the result set is not open, the result set is not scrollable, or an error occurs.
+ **/
+ public void afterLast () throws SQLException
+ {
+ validateResultSet();
+ resultSet_.afterLast();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ }
+
+ /**
+ * Positions the cursor before the first row.
+ * If an InputStream from the current row is open, it is implicitly closed.
+ * In addition, all warnings and pending updates are cleared.
+ *
+ * @exception SQLException If the result set is not open, the result set is not scrollable, or an error occurs.
+ **/
+ public void beforeFirst () throws SQLException
+ {
+ validateResultSet();
+ resultSet_.beforeFirst();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Cancels all pending updates that have been made since the last
+ * call to updateRow(). If no updates have been made or updateRow()
+ * has already been called, then this method has no effect.
+ *
+ * @exception SQLException If the result set is not open
+ * or the result set is not updatable.
+ **/
+ public void cancelRowUpdates () throws SQLException
+ {
+ validateResultSet();
+ resultSet_.cancelRowUpdates();
+ }
+
+ /**
+ * Clears the columns for the current row and releases all associated resources.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void clearParameters() throws SQLException
+ {
+ if (statement_ != null)
+ statement_.clearParameters();
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ resultSet_.clearWarnings();
+ }
+
+ /**
+ * Releases the rowset resources immediately instead of waiting for them to be automatically released.
+ * This closes the connection to the database.
+ *
+ * @exception SQLException If an error occurs.
+ **/
+ public void close () throws SQLException
+ {
+
+ // @D4 change -- don't throw exceptions. Instead, catch and log them. The
+ // user called close so we won't return until we tried to close all
+ // resources.
+ try
+ { // @J4a // @J4a
+ if (resultSet_ != null)
+ resultSet_.close();
+ } // @J4a
+ catch (SQLException e) // @J4a
+ { // @J4a
+ if (JDTrace.isTraceOn()) // @J4a
+ JDTrace.logInformation (this, "Closing result set while closing the row set failed: " + e.getMessage()); // @j4a
+ } // @J4a
+
+
+
+ try
+ { // @J4a // @J4a
+ if (statement_ != null)
+ statement_.close();
+ } // @J4a
+ catch (SQLException e) // @J4a
+ { // @J4a
+ if (JDTrace.isTraceOn()) // @J4a
+ JDTrace.logInformation (this, "Closing statement set while closing the row set failed: " + e.getMessage()); // @j4a
+ } // @J4a
+
+
+
+ if (connection_ != null)
+ connection_.close();
+ }
+
+
+
+ /**
+ * Connects to the database.
+ * @exception SQLException If database errors creating the connection.
+ **/
+ private void connect() throws SQLException
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "connect()");
+
+ if (isUseDataSource())
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "using JDBC DataSource");
+
+ if (dataSourceName_ == null)
+ throw new ExtendedIllegalStateException("dataSourceName", ExtendedIllegalStateException.PROPERTY_NOT_SET);
+
+ try
+ {
+ if (context_ == null) //@A1A
+ {
+ if (environment_ == null) //@A2A
+ context_ = new InitialContext(); //@A1C
+ else //@A2A
+ context_ = new InitialContext(environment_); //@A2A
+ }
+ dataSource_ = (AS400JDBCDataSource)context_.lookup(dataSourceName_);
+ }
+ catch (NamingException ne)
+ {
+ if (JDTrace.isTraceOn ())
+ {
+ JDTrace.logInformation(this, "Cannot find JNDI data source.");
+ ne.printStackTrace(DriverManager.getLogWriter());
+ }
+ throw new ExtendedIllegalStateException("dataSourceName", ExtendedIllegalStateException.OBJECT_CANNOT_BE_FOUND); //@A2C
+ }
+ connection_ = (AS400JDBCConnection)dataSource_.getConnection(username_, password_);
+ }
+ else
+ { // Use the url to make the connection.
+ if (JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "using JDBC url");
+
+ if (url_ == null)
+ throw new ExtendedIllegalStateException("url", ExtendedIllegalStateException.PROPERTY_NOT_SET);
+
+ if (username_ != null && password_ != null)
+ connection_ = DriverManager.getConnection(url_, username_, password_);
+ else
+ connection_ = DriverManager.getConnection(url_);
+ }
+
+ // Set the connection properties.
+ connection_.setReadOnly(isReadOnly_);
+ if (transactionIsolation_ != Connection.TRANSACTION_READ_UNCOMMITTED)
+ connection_.setTransactionIsolation(transactionIsolation_);
+ }
+
+ /**
+ * Creates a statement.
+ * @exception SQLException If a database error occurs creating the statement.
+ **/
+ private void createStatement() throws SQLException
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "createStatement()");
+
+ if (command_ == null)
+ throw new ExtendedIllegalStateException("command", ExtendedIllegalStateException.PROPERTY_NOT_SET);
+
+ if (connection_ == null)
+ connect();
+
+ // set the parameters.
+ int fetchDirection=0, fetchSize=0, maxFieldSize=0, maxRows=0, queryTimeout=0;
+ boolean setParameters = false;
+ if (statement_ != null)
+ {
+ fetchDirection = statement_.getFetchDirection();
+ fetchSize = statement_.getFetchSize();
+ maxFieldSize = statement_.getMaxFieldSize();
+ maxRows = statement_.getMaxRows();
+ queryTimeout = statement_.getQueryTimeout();
+ setParameters = true;
+ }
+ statement_ = (AS400JDBCPreparedStatement)connection_.prepareStatement(command_, type_, concurrency_); //@PDC jdbc40
+
+ if (setParameters)
+ {
+ statement_.setFetchDirection(fetchDirection);
+ statement_.setFetchSize(fetchSize);
+ statement_.setMaxFieldSize(maxFieldSize);
+ statement_.setMaxRows(maxRows);
+ statement_.setQueryTimeout(queryTimeout);
+ }
+ createNewStatement_ = false;
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ resultSet_.deleteRow();
+ }
+
+ /**
+ * Executes the command and fills the rowset with data. Any previous contents are erased.
+ *
+ * The following properties may be used to create a connection for reading data:
+ * 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 columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBytes(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a Java byte array.
+ * This can be used to get values from columns with SQL
+ * types BINARY and VARBINARY.
+ *
+ * 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public byte[] getBytes (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBytes(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a character stream.
+ * This can be used to to get values from columns with SQL
+ * types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and BLOB.
+ * All of the data in the returned stream must be read prior to
+ * getting the value of any other column. The next call to a get
+ * method implicitly closes the stream.
+ *
+ * @param columnIndex 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 Reader getCharacterStream (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getCharacterStream(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a character stream.
+ * This can be used to to get values from columns with SQL
+ * types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and BLOB.
+ * All of the data in the returned stream must be read prior
+ * to getting the value of any other column. The next call
+ * to a get method implicitly closes the 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 name is not valid, or the
+ * requested conversion is not valid.
+ */
+ public Reader getCharacterStream (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getCharacterStream(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a Clob object.
+ * This can be used to get values from columns with SQL
+ * types CHAR, VARCHAR, BINARY, VARBINARY, BLOB, and CLOB.
+ *
+ * @param columnIndex 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 Clob getClob (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getClob(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a Clob object.
+ * This can be used to get values from columns with SQL
+ * types CHAR, VARCHAR, BINARY, VARBINARY, BLOB, and CLOB.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Clob getClob (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getClob(columnName);
+ }
+
+ /**
+ * Returns the command used by the statement the generate the rowset.
+ * This should be set before calling the execute method.
+ * @return The command. The default value is null.
+ **/
+ public String getCommand()
+ {
+ return command_;
+ }
+
+ /**
+ * Returns the result set concurrency.
+ *
+ * @return The result set concurrency.
+ * Valid values are:
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @exception SQLException If the result set is not open,
+ * the result set is not scrollable,
+ * or an error occurs.
+ **/
+ public void moveToCurrentRow () throws SQLException
+ {
+ validateResultSet();
+ resultSet_.moveToCurrentRow();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ }
+
+ /**
+ * Positions the cursor to the insert row.
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ resultSet_.moveToInsertRow();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ }
+
+ /**
+ * Positions the cursor to the next row.
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.next();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+ /**
+ * Positions the cursor to the previous row.
+ * If an InputStream from the current row is open, it is implicitly
+ * closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.previous();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+
+
+ // @A3A
+ /**
+ *Deserializes and initializes transient data.
+ */
+ private void readObject(java.io.ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ initializeTransient();
+ }
+
+
+
+ /**
+ * Refreshes the current row from the database and cancels all
+ * pending updates that have been made since the last call to
+ * updateRow(). This method provides a way for an application
+ * to explicitly refetch a row from the database. If an InputStream
+ * from the current row is open, it is implicitly closed. In
+ * addition, all warnings and pending updates are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ resultSet_.refreshRow();
+ }
+
+ /**
+ * 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.
+ *
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @param rowNumber 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 rowNumber) throws SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.relative(rowNumber);
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+ /**
+ * Removes a PropertyChangeListener.
+ * @param listener The PropertyChangeListener.
+ * @see #addPropertyChangeListener
+ **/
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (listener == null)
+ throw new NullPointerException("listener");
+ changes_.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes the RowSetListener from the list.
+ * @param listener The RowSetListener object.
+ **/
+ public void removeRowSetListener(RowSetListener listener)
+ {
+ eventSupport_.removeRowSetListener(listener);
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.rowDeleted();
+ }
+
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.rowInserted();
+ }
+
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.rowUpdated();
+ }
+
+ /**
+ * Sets the array value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Array object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setArray(int parameterIndex, Array value) throws SQLException
+ {
+ validateStatement();
+ statement_.setArray(parameterIndex, value);
+ }
+
+
+ /**
+ * Sets the inputStream at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * The driver reads the data from the stream as needed until no more bytes are available.
+ * The converts this to an SQL VARCHAR value.
+ *
+ * @param parameterIndex The parameter index (1-based).
+ * @param inputStream The input stream or null to update the value to SQL NULL.
+ * @param length The number of bytes in the stream.
+ * @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 setAsciiStream(int parameterIndex, InputStream inputStream, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setAsciiStream(parameterIndex, inputStream, length);
+ }
+
+ /**
+ * Sets the BigDecimal value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The BigDecimal object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setBigDecimal(int parameterIndex, BigDecimal value) throws SQLException
+ {
+ validateStatement();
+ statement_.setBigDecimal(parameterIndex, value);
+ }
+
+ /**
+ * Sets the binary stream value using a inputStream at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * 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 parameterIndex The parameter index (1-based).
+ * @param inputStream The input stream or null to update the value to SQL NULL.
+ * @param length The number of bytes in the stream.
+ * @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 setBinaryStream(int parameterIndex, InputStream inputStream, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setBinaryStream(parameterIndex, inputStream, length);
+ }
+
+ /**
+ * Sets the Blob value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Blob object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setBlob(int parameterIndex, Blob value) throws SQLException
+ {
+ validateStatement();
+ statement_.setBlob(parameterIndex, value);
+ }
+
+ /**
+ * Sets the boolean value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The boolean value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setBoolean(int parameterIndex, boolean value) throws SQLException
+ {
+ validateStatement();
+ statement_.setBoolean(parameterIndex, value);
+ }
+
+ /**
+ * Sets the byte value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The byte value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setByte(int parameterIndex, byte value) throws SQLException
+ {
+ validateStatement();
+ statement_.setByte(parameterIndex, value);
+ }
+
+ /**
+ * Sets the byte array value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The byte array.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setBytes(int parameterIndex, byte[] value) throws SQLException
+ {
+ validateStatement();
+ statement_.setBytes(parameterIndex, value);
+ }
+
+ /**
+ * Sets a column in the current row using a Reader value.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * 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 parameterIndex The parameter index (1-based).
+ * @param reader The reader or null to update the value to SQL NULL.
+ * @param length The number of characters in the stream.
+ * @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 setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setCharacterStream(parameterIndex, reader, length);
+ }
+
+ /**
+ * Sets the Clob value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Clob object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setClob(int parameterIndex, Clob value) throws SQLException
+ {
+ validateStatement();
+ statement_.setClob(parameterIndex, value);
+ }
+
+ /**
+ * Sets the command used by the execute statement to populate the rowset.
+ * This property is required to create the PreparedStatement.
+ * Resetting the command creates a new PreparedStatement and clears all
+ * existing input parameters.
+ * @param command The command.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setCommand(String command) throws SQLException
+ {
+ String property = "command";
+ if (command == null)
+ throw new NullPointerException(property);
+
+ String old = command_;
+ command_ = command;
+ changes_.firePropertyChange(property, old, command);
+
+ createNewStatement_ = true;
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logProperty (this, property, command);
+ }
+
+ /**
+ * Sets the concurrency type for the result set.
+ * Valid values include:
+ * This setting only affects statements that meet the criteria
+ * specified in the "block criteria" property. The fetch size
+ * is only used if the "block size" property is set to "0".
+ *
+ * @param fetchSize 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 fetchSize) throws SQLException
+ {
+ Integer old = new Integer(getFetchSize());
+
+ if (resultSet_ != null)
+ resultSet_.setFetchSize(fetchSize);
+
+ validateStatement();
+ statement_.setFetchSize(fetchSize);
+
+ changes_.firePropertyChange("fetchSize", old, new Integer(fetchSize));
+ }
+
+ /**
+ * Sets the float value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The float value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setFloat(int parameterIndex, float value) throws SQLException
+ {
+ validateStatement();
+ statement_.setFloat(parameterIndex, value);
+ }
+
+ /**
+ * Sets the integer value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The integer value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setInt(int parameterIndex, int value) throws SQLException
+ {
+ validateStatement();
+ statement_.setInt(parameterIndex, value);
+ }
+
+ /**
+ * Sets the long value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The long value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setLong(int parameterIndex, long value) throws SQLException
+ {
+ validateStatement();
+ statement_.setLong(parameterIndex, value);
+ }
+
+ /**
+ * Sets the maximum column size. The default size is zero indicating no maximum value.
+ * This property is only used with column types:
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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, the
+ * requested conversion is not valid,
+ * the length is not
+ * valid, the input stream does not contain
+ * ASCII characters, or an error happens
+ * while reading the input stream.
+ **/
+ public void updateAsciiStream (int columnIndex, InputStream columnValue, int length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream(columnIndex, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, the
+ * requested conversion is not valid,
+ * the length is not valid,
+ * the input stream does not contain
+ * ASCII characters, or an error happens
+ * while reading the input stream.
+ **/
+ public void updateAsciiStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream(columnName, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a BigDecimal value. The
+ * driver converts this to an SQL NUMERIC value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, BigDecimal columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBigDecimal(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a BigDecimal value. The
+ * driver converts this to an SQL NUMERIC value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateBigDecimal (String columnName, BigDecimal columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBigDecimal (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * This does not update the database directly. Instead, it updates a copy
+ * of the data in memory. Call updateRow() or insertRow() to update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 updateBinaryStream (int columnIndex, InputStream columnValue, int length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream(columnIndex, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid,
+ * the length is not valid, or an error
+ * happens while reading the input stream.
+ **/
+ public void updateBinaryStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream (columnName, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Blob value.
+ The driver converts this to an SQL BLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ @since Modification 5
+ **/
+ public void updateBlob (int columnIndex, Blob columnValue)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Blob value.
+ The driver converts this to an SQL BLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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, Blob columnValue)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using a Java boolean value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, boolean columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBoolean(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java boolean value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateBoolean (String columnName, boolean columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBoolean (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java byte value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, byte columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateByte (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java byte value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateByte (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using a Java byte array value.
+ * The driver converts this to an SQL VARBINARY value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, byte[] columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBytes (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java byte array value.
+ * The driver converts this to an SQL VARBINARY value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateBytes (String columnName, byte[] columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBytes (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream (columnIndex, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, 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,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream (columnName, columnValue, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Clob value.
+ The driver converts this to an SQL CLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue 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.
+ @since Modification 5
+ **/
+ public void updateClob (int columnIndex, Clob columnValue)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using a Java Clob value.
+ The driver converts this to an SQL CLOB value.
+
+ This does not update the database directly. Instead, it updates
+ a copy of the data in memory. Call updateRow() or insertRow() to
+ update the database.
+
+ @param columnName The column name.
+ @param columnValue 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, Clob columnValue)
+ throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using a java.sql.Date value.
+ * The driver converts this to an SQL DATE value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, Date columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateDate (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a java.sql.Date value.
+ * The driver converts this to an SQL DATE value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateDate (String columnName, Date columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateDate (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java double value.
+ * The driver converts this to an SQL DOUBLE value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, double columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateDouble (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java double value.
+ * The driver converts this to an SQL DOUBLE value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateDouble (String columnName, double columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateDouble (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java float value.
+ * The driver converts this to an SQL REAL value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, float columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateFloat (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java float value.
+ * The driver converts this to an SQL REAL value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateFloat (String columnName, float columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateFloat (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using a Java int value.
+ * The driver converts this to an SQL INTEGER value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, int columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateInt (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java int value.
+ * The driver converts this to an SQL INTEGER value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateInt (String columnName, int columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateInt (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, long columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateLong (columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateLong (String columnName, long columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateLong (columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using SQL NULL.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNull (columnIndex);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using SQL NULL.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateNull (String columnName) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNull (columnName);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * 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. In the cases
+ * where an SQL type is not supported by DB2 for IBM i, the
+ * next closest matching type
+ * is used.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, Object columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateObject(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * 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. In the cases
+ * where an SQL type is not supported by DB2 for IBM i, the
+ * next closest matching type
+ * is used.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found,
+ * or the requested conversion is not valid.
+ **/
+ public void updateObject (String columnName, Object columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateObject(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * 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. In the cases
+ * where an SQL type is not supported by DB2 for IBM i, the
+ * next closest matching type
+ * is used.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue The column value or null to update
+ * the value to SQL NULL.
+ * @param scale The number of digits after the decimal
+ * if SQL type is DECIMAL or NUMERIC.
+ *
+ * @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,
+ * the scale is not valid, or the
+ * requested conversion is not valid.
+ **/
+ public void updateObject (int columnIndex, Object columnValue, int scale) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateObject(columnIndex, columnValue, scale);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * 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. In the cases
+ * where an SQL type is not supported by DB2 for IBM i, the
+ * next closest matching type
+ * is used.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue The column value or null to update
+ * the value to SQL NULL.
+ * @param scale The number of digits after the decimal
+ * if SQL type is DECIMAL or NUMERIC.
+ *
+ * @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 name is not found,
+ * the scale is not valid, or the
+ * requested conversion is not valid.
+ **/
+ public void updateObject (String columnName, Object columnValue, int scale) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateObject(columnName, columnValue, scale);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates the database with the new contents of the current row.
+ *
+ * @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 updateRow () throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateRow();
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using an Ref value.
+ DB2 for IBM i does not support structured types.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support REFs.
+ @since Modification 5
+ **/
+ public void updateRef (int columnIndex, Ref columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using an Ref value.
+ DB2 for IBM i does not support structured types.
+
+ @param columnName The column name.
+ @param columnValue The column value or null to update
+ the value to SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support REFs.
+ **/
+ public void updateRef (String columnName, Ref columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ /**
+ * Updates a column in the current row using a Java short value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, short columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateShort(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a Java short value.
+ * The driver converts this to an SQL SMALLINT value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateShort (String columnName, short columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateShort(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a String value.
+ * The driver converts this to an SQL VARCHAR value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, String columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateString(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a String value.
+ * The driver converts this to an SQL VARCHAR value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateString (String columnName, String columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateString(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a java.sql.Time value.
+ * The driver converts this to an SQL TIME value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, Time columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateTime(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a java.sql.Time value.
+ * The driver converts this to an SQL TIME value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateTime (String columnName, Time columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateTime(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ /**
+ * Updates a column in the current row using a java.sql.Timestamp value.
+ * The driver converts this to an SQL TIMESTAMP value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param columnValue 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 columnIndex, Timestamp columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateTimestamp(columnIndex, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Updates a column in the current row using a java.sql.Timestamp value.
+ * The driver converts this to an SQL TIMESTAMP value.
+ *
+ * This does not update the database directly. Instead, it updates
+ * a copy of the data in memory. Call updateRow() or insertRow() to
+ * update the database.
+ *
+ * @param columnName The column name.
+ * @param columnValue 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public void updateTimestamp (String columnName, Timestamp columnValue) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateTimestamp(columnName, columnValue);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ /**
+ * Validates if the connection has been made.
+ **/
+ private void validateConnection()
+ {
+ if (connection_ != null)
+ throw new ExtendedIllegalStateException("connection", ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ /**
+ * Validates if the resultSet has been created.
+ **/
+ private void validateResultSet()
+ {
+ if (resultSet_ == null)
+ throw new ExtendedIllegalStateException("resultSet", ExtendedIllegalStateException.OBJECT_MUST_BE_OPEN);
+ }
+
+ /**
+ * Validates the statement has been created.
+ * @exception SQLException If a database error occurs.
+ **/
+ private void validateStatement() throws SQLException
+ {
+ if (statement_ == null)
+ createStatement();
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.wasNull();
+ }
+
+ //@pda jdbc40
+ /**
+ * Sets the designated parameter to a Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: This stream object can either be a standard
+ * Java stream object or your own subclass that implements the
+ * standard interface.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @param xmlObject the value for the column to be updated
+ * @throws SQLException if a database access error occurs, this method
+ * is called on a closed result set,
+ * the
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param xmlObject the column value
+ * @throws SQLException if a database access error occurs, this method
+ * is called on a closed result set,
+ * the 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
+ * 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 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
+ * 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
+ * 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 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * 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
+ * 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 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * 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
+ * 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
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ * Note: To be portable, applications must give the
+ * SQL type code and the fully-qualified SQL type name when specifying
+ * a NULL user-defined or REF parameter. In the case of a user-defined type
+ * the name is the type name of the parameter itself. For a REF
+ * parameter, the name is the type name of the referenced type. If
+ * a JDBC driver does not need the type code or type name information,
+ * it may ignore it.
+ *
+ * Although it is intended for user-defined and Ref parameters,
+ * this method may be used to set a null parameter of any JDBC type.
+ * If the parameter does not have a user-defined or REF type, the given
+ * typeName is ignored.
+ *
+ *
+ * @param parameterName the name of the parameter
+ * @param sqlType a value from Note: You must specify the parameter's SQL type.
+ *
+ * @param parameterName the name of the parameter
+ * @param sqlType the SQL type code defined in The given Java object will be converted to the given targetSqlType
+ * before being sent to the database.
+ *
+ * If the object has a custom mapping (is of a class implementing the
+ * interface
+ * Note that this method may be used to pass datatabase-
+ * specific abstract data types.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the object containing the input parameter value
+ * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
+ * sent to the database. The scale argument may further qualify this type.
+ * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
+ * this is the number of digits after the decimal point. For all other
+ * types, this value will be ignored.
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed The JDBC specification specifies a standard mapping from
+ * Java Note that this method may be used to pass datatabase-
+ * specific abstract data types, by using a driver-specific Java
+ * type.
+ *
+ * If the object is of a class implementing the interface
+ * This method throws an exception if there is an ambiguity, for example, if the
+ * object is of a class implementing more than one of the interfaces named above.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the object containing the input parameter value
+ * @exception SQLException if a database access error occurs,
+ * this method is called on a closed
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the Note: Consult your JDBC driver documentation to determine if
+ * it might be more efficient to use a version of
+ *
+ * The SQL XML object becomes not readable when this method is called and
+ * may also become not writable depending on implementation.
+ *
+ * @return a stream containing the XML data.
+ * @exception SQLException if there is an error processing the XML value.
+ * The getCause() method of the exception may provide a more detailed exception, for example,
+ * if the stream does not contain valid characters.
+ * An exception is thrown if the state is not readable.
+ */
+ public synchronized Reader getCharacterStream() throws SQLException
+ {
+ Reader r = null;
+ if (lobType == LOB_FREED) {
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ return null;
+ }
+
+ switch (lobType)
+ {
+
+ case SQLData.CLOB:
+ case SQLData.DBCLOB:
+ r = clobValue_.getCharacterStream();
+ break;
+ case SQLData.CLOB_LOCATOR:
+ case SQLData.DBCLOB_LOCATOR:
+ r = clobLocatorValue_.getCharacterStream();
+ break;
+ case SQLData.BLOB:
+ case SQLData.BLOB_LOCATOR:
+ case DOM_DOCUMENT:
+ // Calling getString will do the appropriate conversion
+ String stringValue = this.getString();
+ r = new StringReader(stringValue);
+ break;
+ default:
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, "Invalid value: "+ lobType);
+ return null;
+ }
+ }
+
+ return r;
+ }
+
+
+ /**
+ * Retrieves a string representation of the XML value designated by this
+ * The AS400JDBCSQLXMLLocator class provides the object interface for using XML data through JDBC.
+The mapping in the Java programming language for the SQL XML type.
+XML is a built-in type that stores an XML value as a column value in a row of a database table.
+The SQLXML interface provides methods for accessing the XML value as a String, a Reader or Writer, or as a Stream.
+**/
+public class AS400JDBCSQLXMLLocator extends AS400JDBCSQLXML
+{
+
+
+
+ /**
+ Constructs an AS400JDBCSQLXMLLocator object of Clob/DBClob locator data. (This constructor signature is only
+ available on ClobLocator.)
+ This could be created as a result of an actual XML column or some other data type column and calling resultSet.getSQLXML()
+ The data for the
+ SQLXML will be retrieved as requested, directly from the
+ IBM i system, using the locator handle.
+
+ @param locator The locator.
+ @param converter The text converter.
+ @param savedObject Saved Object.
+ @param savedScale Saved scale.
+ @param isXML Flag that stream is from an XML column type (needed to strip xml declaration)
+ **/
+ AS400JDBCSQLXMLLocator(JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale, boolean isXml)
+ {
+ super();
+ //Since SQLXML has both text and binary getter methods, we need to preserve converter, but need to be able to get
+ //to the bits as binary without doing any conversion or trimming of XML declaration
+
+ //Native JDBC changed to always trim off xml header if accessing data through SQLXML object even it column is not XML...(TB also will now do this)
+ isXml = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+
+ clobLocatorValue_ = new AS400JDBCClobLocator( locator, converter, savedObject, savedScale, isXml); //@xml4 allow AS400JDBCClobLocator to trim off xml header if needed
+ if(isXml)
+ blobLocatorValue_ = new AS400JDBCBlobLocator( locator, savedObject, savedScale); //@xml6 also need ref to bloblocator in case SQLXML.getBinaryStream is called
+
+ lobType = SQLData.CLOB_LOCATOR;
+ isXML_ = isXml; //@xml4
+ }
+
+
+ /**
+ Constructs an AS400JDBCSQLXMLLocator object of BlobLocator data. (This constructor signature is only
+ available on BlobLocator.)
+ The data for the
+ BLOB will be retrieved as requested, directly from the
+ IBM i system, using the locator handle.
+ @param locator The locator.
+ @param savedObject Saved Object.
+ @param savedScale Saved scale.
+ **/
+ AS400JDBCSQLXMLLocator(JDLobLocator locator, Object savedObject, int savedScale)
+ {
+ super();
+ blobLocatorValue_ = new AS400JDBCBlobLocator( locator, savedObject, savedScale);
+ lobType = SQLData.BLOB_LOCATOR;
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+ }
+
+ //@olddesc
+ /**
+ Returns the handle to this locator in the database.
+
+ @return The handle to this locator in the databaes.
+ **/
+ synchronized int getHandle()throws SQLException
+ {
+
+ if(clobLocatorValue_ != null)
+ return clobLocatorValue_.getHandle();
+ else if(blobLocatorValue_ != null)
+ return blobLocatorValue_.getHandle();
+ else
+ return -1; //not set or updated by non-locator value and not needed
+
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCStatement.java b/jdbc40/com/ibm/as400/access/AS400JDBCStatement.java
new file mode 100644
index 000000000..c972b9cde
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCStatement.java
@@ -0,0 +1,4259 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCStatement.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.math.BigDecimal;
+import java.sql.BatchUpdateException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.Enumeration;
+import java.util.Vector;
+
+
+
+// @E6C - Changed javadoc paragraph about thread-safety.
+/**
+ The AS400JDBCStatement class provides a mechanism for
+executing static SQL statements. Use Connection.createStatement()
+to create new Statement objects.
+
+ Only one result set per statement can be open at any point in time.
+Therefore, if an application needs to read from multiple result sets,
+then each must be generated by a different statement.
+
+ AS400JDBCStatements are thread-safe.
+
+ Note that the connection keeps a reference to each statement that
+it creates. This means that statements will not get garbage collected
+until the connection gets garbage collected. It is best to
+explicitly close statements rather than counting on garbage collection.
+**/
+//
+// Implementation notes:
+//
+// 1. The RPB is used to provide parameters for requests.
+// If we make a request without specifying some of the
+// parameters, then the system will look in the RPB.
+//
+// Specifically, we use an RPB for each statement object to
+// store parameters that do not depend on the SQL statement:
+//
+// * cursor name
+// * statement name
+//
+// 2. There are many package-scope members in this class
+// heirarchy which really should be "private protected".
+// However, that is no longer allowed in Java, so we
+// at least limit access out the the package. They
+// are not intended to be used outside of the class
+// hierarchy.
+//
+public class AS400JDBCStatement
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+implements Statement
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+
+ // Constants.
+ static final int MAX_CURSOR_NAME_LENGTH_PRE_V6R1 = 18; //@550C
+ static final int MAX_CURSOR_NAME_LENGTH = 128; //@550A
+
+ // Constants for generated key support
+ static final int RETURN_GENERATED_KEYS = 1; //@G4A
+ static final int NO_GENERATED_KEYS = 2; //@G4A
+ static final int GENERATED_KEYS_NOT_SPECIFIED = -9999; //@G4A
+
+
+ // Private data.
+ boolean allowImmediate_; // private protected
+ private int autoGeneratedKeys_; // @G4A
+ Vector batch_; // private protected
+ private String blockCriteria_;
+ private int blockSize_;
+ private boolean cancelled_;
+ private boolean closed_;
+ private boolean closeOnCompletion_; //@D7A
+ AS400JDBCConnection connection_; // private protected
+ JDCursor cursor_; // private protected
+ private String cursorDefaultName_;
+ private boolean escapeProcessing_;
+ private DBExtendedColumnDescriptors extendedColumnDescriptors_; // @F3A
+ private int fetchDirection_;
+ private int fetchSize_;
+ private AS400JDBCResultSet generatedKeys_; // @G4A
+ int id_; // private protected
+ AS400JDBCStatementLock internalLock_; // private protected // @E6A@C7C
+ private boolean lastPrepareContainsLocator_; // @B2A
+ private int maxFieldSize_;
+ private int maxRows_;
+ int rowsInserted_; // for block insert @G5A
+ private String name_;
+ private String nameOverride_;
+ int numberOfResults_; // private protected
+ int positionOfSyntaxError_; //@F10A
+ boolean prefetch_; // private protected
+ int queryTimeout_; /*@D4A*/
+ private boolean queryTimeoutSet_ = false; /*@B2A*/
+ AS400JDBCResultSet resultSet_; // private protected
+ private int rowCountEstimate_; // @ECA
+ private boolean rpbCreated_;
+ private boolean rpbQueryTimeoutChanged_; //@EFA
+ private boolean rpbSyncNeeded_;
+ JDPackageManager packageManager_; // private protected
+ int resultSetConcurrency_; // private protected
+ int resultSetHoldability_; //@G4A
+ private int resultSetType_;
+ SQLConversionSettings settings_; // private protected
+ private SQLWarning sqlWarning_;
+ JDTransactionManager transactionManager_; // private protected
+ int updateCount_; // private protected
+ private String packageCriteria_; // @A1A
+ int behaviorOverride_ = 0; // @F9a
+ private boolean associatedWithLocators_ = false; //@KBL set to true, if this statement was used to access a locator
+ private boolean holdStatement_ = false; //@KBL set to true, if rpb and ors for this statement should be left open until a transaction boundary
+ protected boolean useVariableFieldCompression_ = false; //@K54 does connection allow compression
+ protected boolean useVariableFieldInsertCompression_ = false; //@K54 does connection allow compressions
+ private boolean isPoolable_ = false; //@PDA jdbc40
+ JDServerRow parameterRow_; // private protected //@re-prep moved from preparedStatement so that it has visibility here
+ private boolean threadInterrupted = false;
+ private DBReplyRequestedDS commonExecuteReply = null; // reply from commonExecute. Note: This cannot be returned to the pool until it is
+ // no longer being used. The data_ pointer from this reply is shared with
+ // all kinds of objects.
+ // Note: Because of the current structure, this can be returned after it is used. The data_
+ // pointer from the reply was created by ClientAccessDataStream.construct. The returnToPool
+ // method for the reply has been corrected to set the data_ pointer back to DBStorage_.data.
+ // @B5A
+ private DBReplyRequestedDS connectReply = null;
+ private DBReplyRequestedDS execImmediateReply = null;
+ private DBReplyRequestedDS normalPrepareReply = null;
+ private DBReplyRequestedDS getMoreResultsReply = null;
+
+ protected boolean queryRunning_; // Used to determine whether or not we need to track}
+ // a QueryCancelThread. @D4A
+ protected AS400JDBCQueryCancelThread cancelThread_; /*@D4A*/
+
+
+
+ /**
+ Constructs an AS400JDBCStatement 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 prefetch Indicates if prefetching data.
+ @param packageCriteria The package criteria.
+ @param resultSetType The result set type.
+ @param resultSetConcurrency The result set concurrency.
+ @param resultSetHoldability The result set holdability.
+ @param autoGeneratedKeys Indicates if auto generated keys were requested.
+
+ @exception SQLException If an error occurs.
+ **/
+ AS400JDBCStatement (AS400JDBCConnection connection,
+ int id,
+ JDTransactionManager transactionManager,
+ JDPackageManager packageManager,
+ String blockCriteria,
+ int blockSize,
+ boolean prefetch,
+ String packageCriteria, // @A1C
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability, // @G4A
+ int autoGeneratedKeys) // @G4A
+ throws SQLException
+ {
+ // Initialization.
+ allowImmediate_ = true;
+ autoGeneratedKeys_ = autoGeneratedKeys; // @G4A
+ //@P0Dbatch_ = new Vector ();
+ blockCriteria_ = blockCriteria;
+ blockSize_ = blockSize;
+ cancelled_ = false;
+ closed_ = false;
+ connection_ = connection;
+ escapeProcessing_ = true;
+ fetchDirection_ = ResultSet.FETCH_FORWARD;
+ fetchSize_ = 0;
+ id_ = id;
+ internalLock_ = new AS400JDBCStatementLock(); // @E6A
+ maxFieldSize_ = 0;
+ maxRows_ = 0;
+ numberOfResults_ = 0;
+ prefetch_ = prefetch;
+ queryTimeout_ = 0;
+ resultSet_ = null;
+ transactionManager_ = transactionManager;
+ updateCount_ = -1;
+ packageManager_ = packageManager;
+ resultSetConcurrency_ = resultSetConcurrency;
+ resultSetHoldability_ = resultSetHoldability; //@G4A
+ resultSetType_ = resultSetType;
+ rpbCreated_ = false;
+ rpbQueryTimeoutChanged_ = false; //@EFA
+ rpbSyncNeeded_ = true;
+ settings_ = SQLConversionSettings.getConversionSettings (connection_);
+ sqlWarning_ = null;
+ packageCriteria_ = packageCriteria; // @A1A
+
+ // By default, the statement name and cursor name are
+ // based on the id.
+ String idString = "0000" + id;
+ String idString4 = idString.substring (idString.length() - 4);
+ name_ = "STMT" + idString4;
+
+ useVariableFieldInsertCompression_ = connection_.useVariableFieldInsertCompression();
+ if(resultSetType_ == ResultSet.TYPE_FORWARD_ONLY) // @B1A
+ {
+ cursorDefaultName_ = "CRSR" + idString4;
+ if(connection_.useVariableFieldCompression()) //@K54
+ useVariableFieldCompression_ = true; //@K54
+ }
+ else // @B1A
+ cursorDefaultName_ = "SCRSR" + idString4; // @B1A
+
+ // @E4D // Use lazy close only when the "lazy close" property @E4A
+ // @E4D // has been set AND the old auto-commit support is @E4A
+ // @E4D // still in effect. @E4A
+ // @E4D boolean lazyClose = connection_.getProperties().getBoolean(JDProperties.LAZY_CLOSE) // @E4A
+ // @E4D && transactionManager_.isNewAutoCommitSupport(); // @E4A
+
+ cursor_ = new JDCursor (connection_, id_, cursorDefaultName_, resultSetConcurrency_); // @E4C @EAC
+
+ //@F4 If the user specified a holdability, then we must check the holdability of
+ //@F4 statements on a Connection.commit or Connection.rollback. Thought about just
+ //@F4 setting this flag to true if the holdability was different than the connection
+ //@F4 holdability, but the connection holdability can change above us.
+ if(resultSetHoldability != AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED) //@F4A
+ {
+ //@F4A
+ connection.setCheckStatementHoldability(true); //@F4A
+ } //@F4A
+
+ try // @F9a
+ {
+ // @F9a
+ behaviorOverride_ = connection_.getProperties().getInt(JDProperties.BEHAVIOR_OVERRIDE); // @F9a
+ } // @F9a
+ catch(Throwable t)
+ {
+ } // @F9a
+
+ // Trace messages.
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logOpen (this, connection_); // @J33c
+ JDTrace.logProperty (this, "Escape processing", escapeProcessing_);
+ JDTrace.logProperty (this, "Fetch direction", fetchDirection_);
+ JDTrace.logProperty (this, "Fetch size", fetchSize_);
+ JDTrace.logProperty (this, "Max field size", maxFieldSize_);
+ JDTrace.logProperty (this, "Max rows", maxRows_);
+ JDTrace.logProperty (this, "Query timeout", queryTimeout_);
+ JDTrace.logProperty (this, "Result set concurrency", resultSetConcurrency_);
+ JDTrace.logProperty (this, "Result set holdability", resultSetHoldability_); //@F4A
+ JDTrace.logProperty (this, "Result set type", resultSetType_);
+ JDTrace.logProperty (this, "Behavior Override", behaviorOverride_); // @F9a
+ String cursorAsString = JDTrace.objectToString(cursor_); // @J33a
+ JDTrace.logInformation(this, "Data to correlate statement with cursor " + cursorAsString); // @J33a
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Adds an SQL statement to the current batch of SQL statements.
+
+ @param sql The SQL statement to be added to the current batch.
+ This can be any SQL statement that does not return
+ a result set.
+
+ @exception SQLException If the statement is not open or
+ the SQL statement contains a syntax
+ error.
+ **/
+ public void addBatch (String sql)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_); //@G4C
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ if(sqlStatement.countParameters () > 0)
+ JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+
+ if(batch_ == null) batch_ = new Vector(); //@P0A
+ batch_.addElement (sqlStatement);
+ }
+ }
+
+
+
+ /**
+ Cancels the statement. This is useful when one thread
+ needs to cancel a statement that is being executed by another
+ thread. This will close the current result set.
+
+ @exception SQLException If the statement is not open or
+ an error occurs.
+ **/
+ public void cancel ()
+ throws SQLException
+ {
+ // Don't synchronize this method... it needs to be callable // @E6A
+ // even when the statement is busy. // @E6A
+ checkOpen ();
+
+ connection_.cancel(id_); // @E5A
+
+ cancelled_ = true;
+ closeResultSet (JDCursor.REUSE_YES);
+ }
+
+
+
+ /**
+ Checks that the statement is open. Public methods
+ that require an open statement should call this first.
+
+ @exception SQLException If the statement is not open.
+ **/
+ void checkOpen ()
+ throws SQLException
+ {
+ connection_.checkOpen ();
+ if(closed_)
+ JDError.throwSQLException (JDError.EXC_FUNCTION_SEQUENCE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Clears the current batch of SQL statements.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public void clearBatch ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ if(batch_ == null) batch_ = new Vector(); //@P0A
+ batch_.removeAllElements ();
+ }
+ }
+
+
+
+ /**
+ Clears all warnings that have been reported for the statement.
+ After this call, getWarnings() returns null until a new warning
+ is reported for the statement.
+
+ @exception SQLException If an error occurs.
+ **/
+ public void clearWarnings ()
+ throws SQLException
+ {
+ sqlWarning_ = null;
+ }
+
+
+
+ /**
+ Releases the statement's resources immediately instead of waiting
+ for them to be automatically released. This closes the current
+ result set.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // Implementation note:
+ //
+ // 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
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ // 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;
+
+ // Close the current result set. (Note: This has no
+ // effect if the user explicitly closed the result set
+ // before closing the statement.
+ //@PDA perf2 comment: if we get back 700,2 from fetch, then cursor is already closed, but resultSet_ is still usable
+ //if(! cursor_.isClosed()) //@perf3 cursor can be closed, but resultset still needs to be closed. closeResultSet checks for closed cursor before closing cursor.
+ //{ // @B3A //@perf3
+ closeResultSet (JDCursor.REUSE_NO);
+ //} // @B3A //@perf3
+
+ // If, even after closing the current result set,
+ // there are more result sets that were returned, we
+ // need to close them, too. At first I though we
+ // would have to Open/Describe and Close each one
+ // in turn, but the database host server allows us to
+ // close the current cursor with REUSE_NO to close
+ // all remaining result sets. The catch is that we
+ // need to have an open cursor before closing it, so
+ // we open the next cursor, then close it again.
+ // This closes all remaining result sets.
+ if(numberOfResults_ > 1)
+ {
+ getMoreResults ();
+ cursor_.close (JDCursor.REUSE_NO);
+ }
+
+ if(generatedKeys_ != null) //@PDA genkeys
+ {
+ generatedKeys_.close();
+ generatedKeys_ = null;
+ }
+
+ //@KBL If the user specified to keep statements open until a transaction boundary and locators are associated
+ // with the statement, do not close the RPB or ORS until a transaction boundary is reached.
+ if(isAssociatedWithLocators() && (connection_.getProperties().getBoolean(JDProperties.HOLD_STATEMENTS)) && (connection_.getAutoCommit() == false))
+ {
+ setHoldStatement(true);
+ closed_ = true; // Want the statement to only be available for use internally, user should not be able to use the statement.
+
+ if (commonExecuteReply != null) { commonExecuteReply.returnToPool(); commonExecuteReply = null; }
+ if (connectReply != null) { connectReply.returnToPool(); connectReply = null; }
+ if (execImmediateReply != null) { execImmediateReply.returnToPool(); execImmediateReply = null; }
+ if (normalPrepareReply != null) { normalPrepareReply.returnToPool(); normalPrepareReply = null; }
+ if (getMoreResultsReply != null) { getMoreResultsReply.returnToPool(); getMoreResultsReply = null; }
+ return; // Mark the statement as closed, but don't notify the connection it has been closed or delete the RPB and ORS.
+ }
+
+ // Delete the RPB. Remember the error information @EDC
+ // in order to report later... @EDC
+ SQLException e = null; // @EDA
+ if(rpbCreated_)
+ { // @EDA
+ DBSQLRPBDS request3 = null; //@P0A
+ DBReplyRequestedDS closeReply = null; //@P0A
+ try
+ { //@P0A
+ request3 = DBDSPool.getDBSQLRPBDS(DBSQLRPBDS.FUNCTIONID_DELETE_RPB, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0); //@P0C
+
+ closeReply = connection_.sendAndReceive(request3, id_); // @EDC @P0C
+
+ int errorClass = closeReply.getErrorClass(); // @EDA
+ int returnCode = closeReply.getReturnCode(); // @EDA
+ if(errorClass != 0)
+ { // @EDA
+ if(returnCode < 0)
+ { // @EDA
+ try
+ { // @EDA
+ JDError.throwSQLException(connection_, id_, errorClass, returnCode); // @EDA
+ } // @EDA
+ catch(SQLException e2)
+ { // @EDA
+ e = e2; // @EDA
+ } // @EDA
+ } // @EDA
+ else
+ { // @EDA
+ postWarning (JDError.getSQLWarning(connection_, id_, errorClass, returnCode)); // @EDA
+ } // @EDA
+ } // @EDA
+ }
+ finally
+ { //@P0A
+ if(request3 != null) {
+ request3.returnToPool(); request3=null;
+ }
+ if(closeReply != null) {
+ closeReply.returnToPool();closeReply=null;
+ }
+ }
+ } // @EDA
+
+ // Delete the ORS.
+ //
+ // @EDD // We must use get a reply here even though we do not
+ // @EDD // need any information from it. Otherwise the next
+ // @EDD // flow would be based on this ORS, which gets deleted.
+ // @EDD // In that case, we would always get an "ORS not found"
+ // @EDD // error.
+ // @EDD //
+ // @EDD // In this case, we also need it to force a send of
+ // @EDD // all of the previous datastreams, since this is the
+ // @EDD // last one for this statement.
+ //
+ // Make sure not to base future requests on this ORS. // @EDA
+ //
+ //@P0DDBSQLResultSetDS request2 = new DBSQLResultSetDS (
+ //@P0D DBSQLResultSetDS.FUNCTIONID_DELETE_RESULTS_SET,
+ //@P0D id_, 0, 0); // @EDC
+ DBSQLResultSetDS request2 = null; //@P0A
+ try
+ { //@P0A
+ request2 = DBDSPool.getDBSQLResultSetDS(DBSQLResultSetDS.FUNCTIONID_DELETE_RESULTS_SET, id_, 0, 0); //@P0C
+
+ connection_.send(request2, id_, false); // @EDC
+ }
+ finally
+ { //@P0A
+ if(request2 != null) {
+ request2.returnToPool(); request2=null;
+ }
+ }
+
+ // Ignore errors, since we would not be able to get
+ // the message text anyway (because the ORS is gone.)
+
+ // free the pooled commonExecuteReply
+ if (commonExecuteReply != null) { commonExecuteReply.returnToPool(); commonExecuteReply = null; }
+ if (connectReply != null) { connectReply.returnToPool(); connectReply = null; }
+ if (execImmediateReply != null) { execImmediateReply.returnToPool(); execImmediateReply = null; }
+ if (normalPrepareReply != null) { normalPrepareReply.returnToPool(); normalPrepareReply = null; }
+ if (getMoreResultsReply != null) { getMoreResultsReply.returnToPool(); getMoreResultsReply = null; }
+ closed_ = true;
+ connection_.notifyClose (this, id_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logClose (this);
+
+ // Rethrow any exception that surfaced when deleting the RPB. @EDA
+ if(e != null) // @EDA
+ throw e; // @EDA
+ }
+ }
+
+ //@KBL
+ /*
+ Finish releasing a partially-closed statement's resources. A statement may become partially closed if, for example,
+ the user called close on the statement and it was associated with a locator.
+ This method will delete any RPB and ORS associated with the statement.".
+ @exception SQLException if an error occurs
+ */
+ void finishClosing()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ // Delete the RPB. Remember the error information
+ // in order to report later...
+ SQLException e = null;
+ if(rpbCreated_)
+ {
+ DBSQLRPBDS request3 = null;
+ DBReplyRequestedDS finishClosingReply = null;
+ try
+ {
+ request3 = DBDSPool.getDBSQLRPBDS(DBSQLRPBDS.FUNCTIONID_DELETE_RPB, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0); //@P0C
+
+ finishClosingReply = connection_.sendAndReceive(request3, id_);
+
+ int errorClass = finishClosingReply.getErrorClass();
+ int returnCode = finishClosingReply.getReturnCode();
+ if(errorClass != 0)
+ {
+ if(returnCode < 0)
+ {
+ try
+ {
+ JDError.throwSQLException(connection_, id_, errorClass, returnCode);
+ }
+ catch(SQLException e2)
+ {
+ e = e2;
+ }
+ }
+ else
+ {
+ postWarning (JDError.getSQLWarning(connection_, id_, errorClass, returnCode));
+ }
+ }
+ }
+ finally
+ {
+ if(request3 != null) { request3.returnToPool(); request3=null; }
+ if(finishClosingReply != null) { finishClosingReply.returnToPool(); finishClosingReply = null; }
+ }
+ }
+
+ // Delete the ORS.
+ //
+ // We must use get a reply here even though we do not
+ // need any information from it. Otherwise the next
+ // flow would be based on this ORS, which gets deleted.
+ // In that case, we would always get an "ORS not found"
+ // error.
+ // In this case, we also need it to force a send of
+ // all of the previous datastreams, since this is the
+ // last one for this statement.
+ //
+ // Make sure not to base future requests on this ORS.
+ DBSQLResultSetDS request2 = null;
+ try
+ {
+ request2 = DBDSPool.getDBSQLResultSetDS(DBSQLResultSetDS.FUNCTIONID_DELETE_RESULTS_SET, id_, 0, 0);
+
+ connection_.send(request2, id_, false);
+ }
+ finally
+ {
+ if(request2 != null) {
+ request2.returnToPool(); request2 = null;
+ }
+ }
+
+ // Ignore errors, since we would not be able to get
+ // the message text anyway (because the ORS is gone.)
+
+ closed_ = true;
+ setHoldStatement(false); //the statement is no longer left open
+ connection_.notifyClose (this, id_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logClose (this);
+
+ // Rethrow any exception that surfaced when deleting the RPB.
+ if(e != null)
+ throw e;
+ }
+
+ }
+
+ /**
+ Closes the result set and cursor.
+
+ @param reuseFlag Either JDCursor.REUSE_NO,
+ JDCursor.REUSE_YES, or
+ JDCursor.REUSE_RESULT_SET.
+
+ @exception SQLException If an error occurs.
+ **/
+ void closeResultSet (int reuseFlag) // private protected
+ throws SQLException
+ {
+ if(resultSet_ != null)
+ {
+ if(! resultSet_.isClosed ())
+ resultSet_.close ();
+ resultSet_ = null;
+ }
+
+ if (threadInterrupted) {
+ // Force a close to be flowed
+ try {
+ cursor_.setState(false);
+ cursor_.close (reuseFlag);
+ } catch (Exception e) {
+
+ }
+ } else {
+ if(! cursor_.isClosed ())
+ cursor_.close (reuseFlag);
+ }
+
+ updateCount_ = -1;
+ }
+
+
+
+ /**
+ Executes an SQL statement on the IBM i system.
+
+ @param sqlStatement The SQL statement.
+ @param resultRow The result row or null if none.
+
+ @exception SQLException If the query timeout limit is
+ exceeded or an error occurs.
+ **/
+ //
+ // Do not override this method. Instead, override
+ // commonExecuteBefore() and commonExecuteAfter() as needed.
+ //
+ final void commonExecute (JDSQLStatement sqlStatement,
+ JDServerRow resultRow) // private protected
+ throws SQLException
+ {
+ SQLException savedException = null; /*@F3A*/
+
+ try {
+ cancelled_ = false;
+
+ /*@D4A*/
+ if (connection_.isQueryTimeoutMechanismCancel()) {
+ startCancelThread();
+ }
+
+ // If the statement is not immediately executable, then
+ // we still need to do the execute. Otherwise, the execute
+ // was already done as part of the prepare.
+ if((! allowImmediate_) || (! sqlStatement.isImmediatelyExecutable ()))
+ {
+
+
+
+ //
+ // If using generated keys, make sure that the prefetch
+ // operation is disabled. If the prefetch option is not
+ // disabled, then it is not possible to the the updated row
+ // count from the insert.
+ // @E5
+ if (autoGeneratedKeys_ == RETURN_GENERATED_KEYS && prefetch_) {
+ prefetch_ = false;
+ }
+
+ // Also close the autogenerated key if it is open.
+ // Breaking the exec into two pieces causes this to be closed
+ // right after the exec if it already is open
+ // @E5
+ if (generatedKeys_ != null) {
+ if (!generatedKeys_.isClosed()) {
+ try {
+ generatedKeys_.close();
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+ // Sync up the RPB.
+ syncRPB ();
+
+ boolean usedNameOverride = false;
+
+ // This boolean is true when an Open is needed and
+ // false when an Execute is needed.
+ boolean openNeeded = (resultRow != null);
+
+ // If we are prefetching data and a row format
+ // was returned, then fetch the first block of data.
+ boolean fetchFirstBlock = ((prefetch_) && (openNeeded));
+
+ // Send the execute data stream.
+ try
+ {
+ // Determine the appropriate function id, based
+ // on whether we want to prefetch data, and on whether
+ // this is an Execute or an Open.
+ int functionId;
+ if(openNeeded)
+ {
+ if(fetchFirstBlock)
+ functionId = DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE_FETCH;
+ else
+ functionId = DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE;
+ }
+ else
+ functionId = DBSQLRequestDS.FUNCTIONID_EXECUTE;
+
+ DBSQLRequestDS request = null; //@P0A
+ // DBReplyRequestedDS replyX = null; //@P0A
+ int openAttributes = 0;
+ try
+ {
+ //@541 When running to a V5R4 or higher system, we can request to get extended column descriptors
+ // from a stored procedure result set. In order to do that, we need to set the extended column
+ // descriptor option on the execute of the statement.
+ boolean isCall = (sqlStatement.getNativeType () == JDSQLStatement.TYPE_CALL); //@541A moved up from farther below in code
+ //@F5D Send this on the prepare, not the execute
+ int requestedORS = DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_SQLCA; //@F3M //@541C undeleted
+ //@F5D //@F3A If we are on a system that supports extended column descriptors and if the //@F3A
+ //@F5D //@F3A user asked for them, send the extended column descriptors code point. //@F3A
+ boolean extendedMetaData = false; //@F3A //@541C undeleted
+ //@F5D if (connection_.getVRM() >= JDUtilities.vrm520) //@F3A
+ if(connection_.getVRM() >= JDUtilities.vrm540 && isCall) //@541A
+ { //@F3A //@541C undeleted
+ extendedMetaData = connection_.getProperties().getBoolean(JDProperties.EXTENDED_METADATA); //@F3A //@541C undeleted
+ if (extendedMetaData) //@F3A //@541C undeleted
+ { //@F3A //@541C undeleted
+ requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_EXTENDED_COLUMN_DESCRIPTORS; //@F3A //@541C undeleted
+ } //@F3A //@541C undeleted
+ } //@F3A //@541C undeleted
+ if(connection_.getVRM() >= JDUtilities.vrm610 ) { //@cur request cursor attributes //@isol
+ requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_CURSOR_ATTRIBUTES; //@cur
+ }
+ //@P0A
+ request = DBDSPool.getDBSQLRequestDS(functionId, id_, requestedORS, 0); //@P0C @F3C @F5C //@541C
+
+ openAttributes = cursor_.getOpenAttributes(sqlStatement, blockCriteria_); //@F7M
+ if(openNeeded)
+ {
+ //@F7D openAttributes = cursor_.getOpenAttributes (sqlStatement, blockCriteria_);
+ if((autoGeneratedKeys_ == RETURN_GENERATED_KEYS) && connection_.getVRM() >= JDUtilities.vrm610) //@GKA Wrapped INSERT WITH SELECT for generated keys. Result set should be read only, insensitive
+ request.setOpenAttributes(0x80); //@GKA
+ else //@GKA
+ request.setOpenAttributes(openAttributes);
+ }
+ else if(extendedMetaData){ //@541A Doing an execute. If running to V5R4 and higher, and the extendedMetaData property is true, set the extended column descriptor option
+ request.setExtendedColumnDescriptorOption((byte)0xF1);
+ }
+
+ if(nameOverride_.length() != 0)
+ {
+ request.setPrepareStatementName(nameOverride_, connection_.converter_); //@P0C
+ usedNameOverride = true;
+ }
+
+ if(packageManager_.isEnabled() && sqlStatement.isPackaged())
+ {
+ request.setPackageName (packageManager_.getName (), connection_.converter_); //@P0C
+ }
+
+ String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@H1A
+
+ // If we are prefetching data and a row format
+ // was returned, then set the blocking factor if a specific number of rows have been asked for
+ // or variable-length field compression is turned off, otherwise set the buffer size.
+ if(fetchFirstBlock)
+ {
+ request.addOperationResultBitmap(DBSQLRequestDS.ORS_BITMAP_RESULT_DATA);
+ if((functionId == DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE_FETCH) && //@K54
+ (useVariableFieldCompression_)) //@K54
+ {
+ //Do not need to set the blocking factor if using variable-length field compression
+ //If both the buffer size and blocking factor were set, the buffer size will override
+ //the blocking factor and the number of rows that will fit in the buffer size will be returned
+ //regardless of the blocking factor value
+ request.setVariableFieldCompression(true);
+ request.setBufferSize(blockSize_ * 1024);
+ }
+ else { //@K54
+
+ if (resultRow != null) { // @B5A -- check for null pointer
+ request.setBlockingFactor(getBlockingFactor (cursorSensitivity, sqlStatement, resultRow.getRowLength())); //@K54 changed to just use resultRow.getRowLength() instead of fetchFirstBlock ? resultRow.getRowLength() : 0
+ } else {
+ request.setBlockingFactor(getBlockingFactor (cursorSensitivity, sqlStatement, 0)); //@K54 changed to just use resultRow.getRowLength() instead of fetchFirstBlock ? resultRow.getRowLength() : 0
+ }
+ }
+ }
+
+ //@K1D //@F8 If we are pre-V5R2, the user set the resultSetType to "TYPE_SCROLL_INSENSITIVE", or
+ //@K1D //@F8 the user did not change from the default of the "cursor sensitivity" property,
+ //@K1D //@F8 send what we always have.
+ //@K1D //@F8 Change in a future release to send CURSOR_SCROLLABLE_INSENSITIVE and
+ //@K1D //@F8 CURSOR_NOT_SCROLLABLE_INSENSITIVE if resultSetType_ ==
+ //@K1D //@F8 ResultSet.TYPE_SCROLL_INSENSITIVE to v5r1 or later hosts.
+ // String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F8A
+ //@K1D if((connection_.getVRM() < JDUtilities.vrm520) //@F8A
+ //@K1D || (resultSetType_ == ResultSet.TYPE_SCROLL_INSENSITIVE) //@F8A
+ //@K1D || (cursorSensitivity.equalsIgnoreCase(JDProperties.CURSOR_SENSITIVITY_ASENSITIVE))) //@F8A
+ //@K1D {
+ //@K1D if(resultSetType_ == ResultSet.TYPE_FORWARD_ONLY)
+ //@K1D request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_ASENSITIVE);
+ //@K1D else
+ //@K1D request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_SCROLLABLE_ASENSITIVE);
+ //@K1D }
+ //@K1D //@F8 If we are V5R2 or later, send new numbers based on what the user
+ //@K1D //@F8 set in "cursor sensitivity" property //@F8A
+ //@K1D else if(resultSetType_ == ResultSet.TYPE_FORWARD_ONLY)
+ //@K1D {
+ //@K1D if(cursorSensitivity.equalsIgnoreCase(JDProperties.CURSOR_SENSITIVITY_INSENSITIVE)) //@F8A
+ //@K1D request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_INSENSITIVE); //@F8A
+ //@K1D else //else property set to sensitive //@F8A
+ //@K1D request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_SENSITIVE); //@F8A
+ //@K1D }
+ //@K1D //@F8 Else, resultSetType_ is ResultSet.TYPE_CURSOR_SENSITIVE
+ //@K1D else
+ //@K1D {
+ //@K1D if(cursorSensitivity.equalsIgnoreCase(JDProperties.CURSOR_SENSITIVITY_INSENSITIVE)) //@F8A
+ //@K1D request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_SCROLLABLE_INSENSITIVE); //@F8A
+ //@K1D else //else property set to sensitive //@F8A
+ //@K1D request.setScrollableCursorFlag(DBSQLRequestDS.CURSOR_SCROLLABLE_SENSITIVE); //@F8A
+ //@K1D }
+ //If earlier than V5R2, do what we always have //@K1A
+ if(connection_.getVRM() < JDUtilities.vrm520) //@K1A
+ {
+ //@K1A
+ if(resultSetType_ == ResultSet.TYPE_FORWARD_ONLY) //@K1A
+ request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_ASENSITIVE); //@K1A Option 0
+ else //@K1A
+ request.setScrollableCursorFlag (DBSQLRequestDS.CURSOR_SCROLLABLE_ASENSITIVE); //@K1A Option 1
+ } //@K1A
+ else if ((autoGeneratedKeys_ == RETURN_GENERATED_KEYS) && connection_.getVRM() >= JDUtilities.vrm610) //@GKA
+ { //@GKA
+ // The user requested generated keys so we wrapped the INSERT with a SELECT //@GKA
+ // The result set returned will be for the generated keys and should be read-only, insensitive //@GKA
+ // We want to ignore any property or settings specified on the STATEMENT or CONNECTION //@GKA
+ request.setScrollableCursorFlag(DBSQLRequestDS.CURSOR_SCROLLABLE_INSENSITIVE); //@GKA
+ } //@GKA
+ else {
+ /* @H1A Use common routine to determine scrollability */
+ request.setScrollableCursorFlag(
+ AS400JDBCResultSet.getDBSQLRequestDSCursorType(cursorSensitivity, resultSetType_, resultSetConcurrency_));
+ }
+
+ // Check system level before sending new code point
+ if(connection_.getVRM() >= JDUtilities.vrm520) // @G4A
+ {
+ // @G4A
+ if(resultSetHoldability_ == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT) // @G4A
+ request.setResultSetHoldabilityOption((byte)0xD5); // @G4A
+ else if(resultSetHoldability_ == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) // @G4A
+ request.setResultSetHoldabilityOption((byte)0xE8); // @G4A
+ // else resultSetHoldability_ == AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED, // @G4A
+ // so don't send the code point because the user did not tell us to // @G4A
+ }
+
+ commonExecuteBefore(sqlStatement, request);
+
+ if (commonExecuteReply != null) { commonExecuteReply.returnToPool(); commonExecuteReply=null; }
+
+ commonExecuteReply = connection_.sendAndReceive(request, id_); //@P0C
+
+
+ // Gather information from the reply.
+ cursor_.processConcurrencyOverride(openAttributes, commonExecuteReply); // @E1A @EAC
+
+ cursor_.processCursorAttributes(commonExecuteReply); //@cur
+
+ transactionManager_.processCommitOnReturn(commonExecuteReply); // @E2A
+ DBReplySQLCA sqlca = commonExecuteReply.getSQLCA();
+ DBData resultData = null;
+ if(fetchFirstBlock) resultData = commonExecuteReply.getResultData();
+
+ // Note the number of rows inserted/updated
+ rowsInserted_ = sqlca.getErrd(3); // @G5A
+
+ // Check for system errors. Take note on prefetch
+ // if the last block was fetched.
+ int errorClass = commonExecuteReply.getErrorClass();
+ int returnCode = commonExecuteReply.getReturnCode();
+
+ // Remember that a cursor is open even when most
+ // errors occur.
+ //
+ // Except:
+ // * When a query timeout occurs, the system
+ // does not leave a cursor open.
+ if(openNeeded && (errorClass != 1 || returnCode != -666)) cursor_.setState(false);
+
+ // Take note on prefetch if the last block was fetched.
+ boolean lastBlock = false;
+ boolean bypassExceptionWarning = false; //@pda (issue 32120) in special errorClass/returnCode cases below, we use sqlca to see if there is a real error
+ if((((errorClass == 1) && (returnCode == 100))
+ || ((errorClass == 2) && (returnCode == 701)))
+ && functionId == DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE_FETCH) // make sure we attempted to prefetch data, otherwise post a warning
+ {
+ lastBlock = true;
+ returnCode = sqlca.getSQLCode(); //@pda (issue 32120) get rc from SQLCA
+ String sqlState = sqlca.getSQLState (connection_.converter_); //@issue 34500
+ if(sqlState.startsWith("00") || sqlState.startsWith("02")) //@pda (issue 32120) //@issue 34500 //@35199
+ bypassExceptionWarning = true; //@pda (issue 32120)
+ }
+ else if((errorClass == 2) && (returnCode == 700)
+ && (functionId == DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE_FETCH)) //@pda perf2 - fetch/close
+ {
+ lastBlock = true;
+ cursor_.setState(true); //closed cursor already on system
+ returnCode = sqlca.getSQLCode(); //@pda (issue 32120) get rc from SQLCA
+ String sqlState = sqlca.getSQLState (connection_.converter_); //@issue 34500
+ if(sqlState.startsWith("00") || sqlState.startsWith("02")) //@pda (issue 32120) //@issue 34500 //@35199
+ bypassExceptionWarning = true; //@pda (issue 32120)
+ }
+
+
+ //else //@PDD check for errors even on cases above (issue 32120)
+ if(errorClass != 0 && bypassExceptionWarning == false) //@pdc (issue 32120)
+ {
+ positionOfSyntaxError_ = sqlca.getErrd(5); //@F10A
+
+ if(returnCode < 0)
+ {
+ //
+ // Check if error came from a combined opened fetch...
+ // If so, delay error until fetch occurs. @F3A
+ //
+ int errd6 = sqlca.getErrd(6);
+ if ( errd6 == 1) {
+ // Delay error
+ try {
+ JDError.throwSQLException(connection_, id_, errorClass, returnCode);
+ } catch (SQLException e) {
+ savedException = e;
+ }
+ } else {
+
+ JDError.throwSQLException(connection_, id_, errorClass, returnCode);
+ }
+ }
+ else
+ {
+ String sqlState = sqlca.getSQLState (connection_.converter_); //@igwrn
+ if( connection_.getProperties().getString(JDProperties.IGNORE_WARNINGS).toUpperCase().indexOf(sqlState) == -1 ) //@igwrn
+ postWarning(JDError.getSQLWarning(connection_, id_, errorClass, returnCode));
+ }
+ }
+
+ //Make an auto-generated key result set if it was requested //@G4A
+ if(autoGeneratedKeys_ == RETURN_GENERATED_KEYS && //@G4A
+ (connection_.getVRM() >= JDUtilities.vrm520) &&
+ ((connection_.getVRM() < JDUtilities.vrm610) || !sqlStatement.isSelectFromInsert())) //@F5A @F6C @GKC
+ //@F6D&& generatedKeys_ == null) //@F5A
+ makeGeneratedKeyResultSet(returnCode, sqlca); //@G4A
+ else if(generatedKeys_ != null) //@PDA genkeys - handle previous genkeys
+ {
+ generatedKeys_.close();
+ generatedKeys_ = null;
+ }
+
+
+ //@F5D This belongs on the prepare, not the execute
+ //@F5D @F3A If user asked us to parse out extended metadata, then make an object
+ //@K3A Added back.. This belongs here for stored procedure result sets
+ // extendedMetaData is set to true only for all statements.
+ if (extendedMetaData) //@F3A
+ { //@F3A
+ extendedColumnDescriptors_ = commonExecuteReply.getExtendedColumnDescriptors(); //@F3A
+ } //@F3A
+
+ // Compute the update count and result set .
+ if(openNeeded)
+ {
+ // @B5A Check for null pointer.
+ int rowLength = 0;
+ if (resultRow != null) {
+ rowLength = resultRow.getRowLength();
+ }
+ JDServerRowCache rowCache;
+ if((fetchFirstBlock) && (resultData != null))
+ rowCache = new JDServerRowCache (resultRow,
+ connection_, id_,
+ getBlockingFactor (cursorSensitivity, sqlStatement, rowLength), resultData,
+ lastBlock, resultSetType_, cursor_); //@pdc perf2 - fetch/close
+ else
+ rowCache = new JDServerRowCache (resultRow,
+ connection_, id_,
+ getBlockingFactor (cursorSensitivity, sqlStatement, rowLength), lastBlock, resultSetType_, cursor_); //@PDC perf //@pdc perf2 - fetch/close
+
+ // If the result set concurrency is updatable, check to @E1C
+ // see if the system overrode the cursor type to read only. @E1C
+ // Don't worry about the other direction (system overrides @E1C
+ // from read-only to updatable). @E1C
+ int actualConcurrency = (resultSetConcurrency_ == ResultSet.CONCUR_UPDATABLE) // @E1C
+ ? cursor_.getConcurrency() : resultSetConcurrency_; // @E1C @EAC
+
+ if((autoGeneratedKeys_ == RETURN_GENERATED_KEYS) &&
+ (connection_.getVRM() >= JDUtilities.vrm610) &&
+ sqlStatement.isSelectFromInsert()) //@GKA
+ {
+ // this will be the generated keys result set //@GKA
+ updateCount_ = sqlca.getErrd(3); //@GKA
+ rowCountEstimate_ = -1; //@GKA
+ generatedKeys_ = new AS400JDBCResultSet (this, sqlStatement, rowCache, connection_.getCatalog(),//@GKA
+ cursor_.getName(), maxRows_, //@GKA
+ ResultSet.TYPE_SCROLL_INSENSITIVE, //@GKA
+ ResultSet.CONCUR_READ_ONLY, fetchDirection_, fetchSize_); //@GKA
+ } //@GKA
+ else //@GKA
+ { //@GKA
+ updateCount_ = -1; // @ECM
+ rowCountEstimate_ = sqlca.getErrd (3); //@F1C // @ECA
+ resultSet_ = new AS400JDBCResultSet (this,
+ sqlStatement, rowCache, connection_.getCatalog(),
+ cursor_.getName(), maxRows_, resultSetType_,
+ actualConcurrency, fetchDirection_, fetchSize_); // @E1C
+ if(resultSet_.getConcurrency () != resultSetConcurrency_ && resultSetConcurrency_ == ResultSet.CONCUR_UPDATABLE) //@nowarn only warn if concurrency level is lessened
+ postWarning (JDError.getSQLWarning (JDError.WARN_OPTION_VALUE_CHANGED));
+ if (savedException != null) { /*@F3A*/
+ resultSet_.addSavedException(savedException);
+ }
+ } //@GKA
+ }
+ else
+ {
+ updateCount_ = sqlca.getErrd (3); //@F1C
+ rowCountEstimate_ = -1; // @ECC
+ }
+
+ // Compute the number of results.
+ //@541D boolean isCall = (sqlStatement.getNativeType () == JDSQLStatement.TYPE_CALL);
+ if(isCall)
+ numberOfResults_ = sqlca.getErrd (2); //@F1C
+ else
+ numberOfResults_ = 0;
+
+ if(extendedMetaData) //@541A
+ {
+ extendedColumnDescriptors_ = commonExecuteReply.getExtendedColumnDescriptors (); //@F5A
+ cursor_.setExtendedMetaData(extendedMetaData); //@K3A
+ }
+
+ // If this is a CALL and result sets came back, but
+ // no format was returned, then open the cursor. The
+ // result set must be forward only and read only.
+ // This is a system restriction. @EBA
+ // As of V5R3 the restriction to be forward only no longer applies @KBA
+ if(sqlStatement != null)
+ {
+ if((isCall) && (numberOfResults_ > 0) && (resultSet_ == null))
+ {
+ boolean preV5R3 = connection_.getVRM() < JDUtilities.vrm530;
+
+ // Change the result set type based on the current attributes
+ // unless forward only cursors were requested. This must
+ // be kept in sync with similar code ins AS400JDBCResultSet
+ // @C4A
+ int callResultSetType ;
+ if (resultSetType_ == ResultSet.TYPE_FORWARD_ONLY) {
+ // The user requested FORWARD_ONLY, so the result set will
+ // only be usable as forward only.
+ callResultSetType = ResultSet.TYPE_FORWARD_ONLY;
+ } else if(cursor_.getCursorAttributeScrollable() == 0)
+ callResultSetType = ResultSet.TYPE_FORWARD_ONLY;
+ else if(cursor_.getCursorAttributeSensitive() == 0)
+ callResultSetType = ResultSet.TYPE_SCROLL_INSENSITIVE;
+ else if(cursor_.getCursorAttributeSensitive() == 1)
+ callResultSetType = ResultSet.TYPE_SCROLL_SENSITIVE;
+ else
+ callResultSetType = resultSetType_;
+
+ JDServerRow row = new JDServerRow (
+ connection_, id_, cursor_.openDescribe (openAttributes,
+ callResultSetType), settings_); //@KBA
+ JDServerRowCache rowCache = new JDServerRowCache (row,
+ connection_, id_,
+ getBlockingFactor (cursorSensitivity, sqlStatement,
+ row.getRowLength()), false, (preV5R3 ? ResultSet.TYPE_FORWARD_ONLY : resultSetType_), cursor_); //@PDC perf //@pda perf2 - fetch/close
+ //if pre-v5r3 create a FORWARD_ONLY RESULT SET
+
+ if(preV5R3) //@KBA
+ {
+ resultSet_ = new AS400JDBCResultSet (this,
+ sqlStatement, rowCache, connection_.getCatalog(),
+ cursor_.getName(), maxRows_, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, fetchDirection_,
+ fetchSize_);
+ }
+ else //@KBA
+ { //@KBA
+ resultSet_ = new AS400JDBCResultSet (this, //@KBA
+ sqlStatement, rowCache, connection_.getCatalog(), //@KBA
+ cursor_.getName(), maxRows_, callResultSetType, //@KBA
+ ResultSet.CONCUR_READ_ONLY, fetchDirection_, //@KBA
+ fetchSize_); //@KBA
+ }
+
+ if(resultSet_.getConcurrency () != resultSetConcurrency_)
+ postWarning (JDError.getSQLWarning (JDError.WARN_OPTION_VALUE_CHANGED));
+
+ /*@K3A*/
+ if (extendedMetaData) {
+ DBExtendedColumnDescriptors newExtendedColumnDescriptors = cursor_.getExtendedColumnDescriptors();
+ if (newExtendedColumnDescriptors != null) {
+ extendedColumnDescriptors_ = newExtendedColumnDescriptors;
+ }
+ }
+ }
+ }
+
+ commonExecuteAfter (sqlStatement, commonExecuteReply);
+ } catch (SQLException sqlex) {
+
+ // Handle interrupted exception
+ String messageText = sqlex.getMessage();
+ messageText = messageText.toLowerCase();
+ if (messageText.indexOf("internal driver error") >= 0) {
+ if (messageText.indexOf("interrupted") > 0) {
+ threadInterrupted = true;
+ }
+ }
+ throw sqlex;
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request = null;
+ }
+ // This can be returned. See comment at declaration. @B5A
+ if (commonExecuteReply != null) { commonExecuteReply.returnToPool(); commonExecuteReply = null; }
+
+ }
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+
+ // Inform the transaction manager that a statement
+ // was executed.
+ transactionManager_.statementExecuted ();
+
+ // Check to see if the statement was cancelled.
+ if(cancelled_)
+ JDError.throwSQLException (JDError.EXC_OPERATION_CANCELLED);
+
+ // Output a summary as a trace message. The * signifies that the
+ // statement name comes from the RPB.
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this,
+ "Executed " + (usedNameOverride ? (nameOverride_) : (name_ + "*"))
+ + ", SQL Statement --> [" + sqlStatement + "]");
+ JDTrace.logInformation (this,
+ "Update count = " + updateCount_);
+ JDTrace.logInformation (this,
+ "Result set = " + (resultSet_ != null));
+ JDTrace.logInformation (this,
+ "Number of result sets = " + numberOfResults_);
+ JDTrace.logInformation (this, // @ECA
+ "Row count estimate = " + rowCountEstimate_); // @ECA
+ }
+ }
+ } finally {
+ /*@D4A*/
+ if (connection_.isQueryTimeoutMechanismCancel()) {
+ endCancelThread();
+ }
+
+ }
+ }
+
+
+ /**
+ Performs common operations needed after an execute.
+
+ @param sqlStatement The SQL statement.
+ @param reply The execute reply.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This method is intended to be overriden, if needed.
+ //
+ void commonExecuteAfter (JDSQLStatement sqlStatement,
+ DBReplyRequestedDS reply) // private protected
+ throws SQLException
+ {
+ // Nothing.
+ }
+
+
+
+ /**
+ Performs common operations needed before an execute.
+
+ @param sqlStatement The SQL statement.
+ @param request The execute request.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This method is intended to be overriden, if needed.
+ //
+ void commonExecuteBefore (JDSQLStatement sqlStatement,
+ DBSQLRequestDS request) // private protected
+ throws SQLException
+ {
+ // Clear warnings.
+ clearWarnings ();
+ }
+
+
+
+ /**
+ Prepares (pre-compiles) the SQL statement on the IBM i system.
+
+ @param sqlStatement The SQL statement.
+ @return The result row or null if none.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // Do not override this method. Instead, override
+ // commonPrepareBefore(), commonPrepareAfter() and
+ // commonPrepareBypass() as needed.
+ //
+ JDServerRow commonPrepare (JDSQLStatement sqlStatement) // private protected
+ throws SQLException
+ {
+ JDServerRow resultRow = null;
+ try {
+ /*@D4A*/
+ if (connection_.isQueryTimeoutMechanismCancel()) {
+ startCancelThread();
+ }
+
+ cancelled_ = false;
+
+ connection_.checkAccess (sqlStatement);
+ nameOverride_ = "";
+
+ // Check for DRDA connect or disconnect. @B1A
+ if(sqlStatement.isDRDAConnect ())
+ {
+ connection_.setDRDA (true);
+
+ // It is possible at this point, that current statement
+ // id does not follow the DRDA rules (defined in
+ // AS400JDBCConnection.getUnusedId()), but we will not
+ // work around that at this point. This simple workaround
+ // is to create a new Statement immediately after connecting.
+ }
+ else if(sqlStatement.isDRDADisconnect ())
+ connection_.setDRDA (false);
+
+ // Create the SQL package if necessary.
+ if(! packageManager_.isCreated())
+ packageManager_.create ();
+
+ // There are three distinct cases. Exactly one of these
+ // branches will be taken.
+
+ // CASE 1: The statement appears in the cached package.
+ //
+ // If the SQL package is cached, check to see if this SQL
+ // statement is in there. If so, then gather data accordingly
+ // and skip the prepare.
+ //
+ if(packageManager_.isCached())
+ {
+ if(sqlStatement.isPackaged())
+ {
+ int i = packageManager_.getCachedStatementIndex (sqlStatement);
+ if(i != -1)
+ {
+
+ // Gather results from package cache.
+ DBDataFormat dataFormat = packageManager_.getCachedDataFormat (i);
+ if(dataFormat == null)
+ resultRow = null;
+ else
+ resultRow = new JDServerRow (connection_, id_,
+ dataFormat, settings_);
+ //@re-prep check if one of the columns is a lob or locator on resultset columns
+ if( resultRow != null && resultRow.containsLob_) //@re-prep
+ {
+ resultRow = null; //@re-prep output lobs
+ } //@re-prep
+
+ commonPrepareBypass (sqlStatement, i);
+
+ //@re-prep input lobs on prepared statement
+ if(parameterRow_ != null && parameterRow_.containsLob_) //@re-prep
+ { //@re-prep
+ nameOverride_ = ""; //@re-prep
+ // Output a summary as a trace message.
+ if(JDTrace.isTraceOn()) //@re-prep
+ JDTrace.logInformation (this,
+ "Statement [" + sqlStatement + "] was found "
+ + "in the cached package "
+ + " but must be re-prepared since it contains a lob or locator"); //@re-prep
+ } //@re-prep
+ else //@re-prep
+ { //@re-prep
+ nameOverride_ = packageManager_.getCachedStatementName (i);
+ // Output a summary as a trace message.
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this,
+ "Statement [" + sqlStatement + "] was found "
+ + "in the cached package as " + nameOverride_);
+ } //@re-prep
+ }
+ }
+ }
+
+ // If the SQL package is not cached, then we must prepare
+ // the statement on the system.
+ if(nameOverride_.length() == 0)
+ {
+
+ // @E7A - start
+ //
+ // CASE 2a: Statement is a DRDA CONNECT.
+ //
+ if(sqlStatement.getNativeType() == JDSQLStatement.TYPE_CONNECT)
+ {
+
+ // Sync up the RPB.
+ syncRPB();
+
+ DBSQLRequestDS request = null; //@P0A
+ try
+ {
+
+ request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_CONNECT, id_, DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_SQLCA, 0); //@P0C
+
+ boolean extended = false; //@540
+ if(connection_.getVRM() >= JDUtilities.vrm540) extended = true; //@540
+ //Bidi-HCG request.setStatementText(sqlStatement.toString(), connection_.unicodeConverter_, extended); //@E3C @P0C @540C
+ request.setStatementText(sqlStatement.toString(), connection_.packageCCSID_Converter, extended);//Bidi-HCG
+ request.setStatementType (sqlStatement.getNativeType ());
+
+ if(packageManager_.isEnabled())
+ {
+ if(sqlStatement.isPackaged())
+ {
+ request.setPrepareOption (1);
+ request.setPackageName (packageManager_.getName (), connection_.converter_); //@P0C
+ }
+ else
+ {
+ request.setPrepareOption (0);
+ request.setPackageName(null, connection_.converter_); //send empty code point per
+ }
+ }
+ else
+ request.setPrepareOption (0);
+
+ commonPrepareBefore (sqlStatement, request);
+ commonExecuteBefore (sqlStatement, request);
+
+ if (execImmediateReply != null) {
+ execImmediateReply.returnToPool(); execImmediateReply = null;
+ }
+ if (normalPrepareReply != null) {
+ normalPrepareReply.returnToPool();normalPrepareReply = null;
+ }
+ if (connectReply != null) { connectReply.returnToPool(); connectReply=null; }
+ connectReply = connection_.sendAndReceive (request, id_); //@P0C
+
+ int errorClass = connectReply.getErrorClass();
+ int returnCode = connectReply.getReturnCode();
+
+ if(errorClass != 0)
+ {
+ positionOfSyntaxError_ = connectReply.getSQLCA().getErrd(5); //@F10A
+
+ if(returnCode < 0)
+ JDError.throwSQLException (connection_, id_, errorClass, returnCode);
+ else
+ postWarning (JDError.getSQLWarning (connection_, id_, errorClass, returnCode));
+ }
+
+ // Compute the update count and number of results.
+ updateCount_ = 0;
+ numberOfResults_ = 0;
+
+ commonPrepareAfter (sqlStatement, connectReply);
+ commonExecuteAfter (sqlStatement, connectReply);
+
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request=null;
+ }
+ if (connectReply != null) { connectReply.returnToPool(); connectReply = null; } /*@B5A*/
+
+ }
+
+ // Inform the transaction manager that a statement
+ // was executed.
+ transactionManager_.statementExecuted ();
+
+ // Output a summary as a trace message. The * signifies that the
+ // statement name comes from the RPB.
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this,
+ "Executed connect " + name_ + "*, SQL Statement -->[" + sqlStatement + "]");
+ }
+
+ }
+ // @E7A - end
+
+ // CASE 2: Statement can be executed immediately.
+ //
+ // This is essentially the prepare and execute combined
+ // in one datastream. We will then be able to skip the
+ // execute step later.
+ //
+ else if((allowImmediate_) && (sqlStatement.isImmediatelyExecutable ()))
+ { // @E7C
+
+ // Sync up the RPB.
+ syncRPB ();
+
+ DBSQLRequestDS request = null; //@P0A
+ try
+ {
+
+ int requestedORS = DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_SQLCA; //@F5A
+ boolean isCall = (sqlStatement.getNativeType () == JDSQLStatement.TYPE_CALL); //@cur
+ if(connection_.getVRM() >= JDUtilities.vrm610 ) //@cur //@isol
+ requestedORS += DBSQLRequestDS.ORS_BITMAP_CURSOR_ATTRIBUTES; //@cur
+ //@F5A If we are on a system that supports extended column descriptors and if the //@F5A
+ //@F5A user asked for them, send the extended column descriptors code point. //@F5A
+ boolean extendedMetaData = false; //@F5A
+ if(connection_.getVRM() >= JDUtilities.vrm520) //@F5A
+ {
+ //@F5A
+ extendedMetaData = connection_.getProperties().getBoolean(JDProperties.EXTENDED_METADATA); //@F5A
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_EXTENDED_COLUMN_DESCRIPTORS; //@F5A
+ } //@F5A
+ }
+
+ request = DBDSPool.getDBSQLRequestDS (DBSQLRequestDS.FUNCTIONID_EXECUTE_IMMEDIATE, id_, requestedORS, 0); //@P0C @F5C
+
+ boolean extended = false; //@540
+ if(connection_.getVRM() >= JDUtilities.vrm540) extended = true; //@540
+ //Bidi-HCG request.setStatementText(sqlStatement.toString(), connection_.unicodeConverter_, extended); //@E3C @P0C @540C
+ request.setStatementText(sqlStatement.toString(), connection_.packageCCSID_Converter, extended);//Bidi-HCG
+ request.setStatementType (sqlStatement.getNativeType ());
+
+ int openAttributes = cursor_.getOpenAttributes (sqlStatement, blockCriteria_);
+ request.setOpenAttributes (openAttributes);
+
+ if(packageManager_.isEnabled())
+ {
+ if(sqlStatement.isPackaged())
+ {
+ request.setPrepareOption (1);
+ request.setPackageName (packageManager_.getName (), connection_.converter_); //@P0C
+ }
+ else
+ {
+ request.setPrepareOption (0);
+ request.setPackageName(null, connection_.converter_); //send empty code point
+ }
+ }
+ else
+ request.setPrepareOption (0);
+
+ //@F5A Don't have to check if a v5r2 system, because extendedMetaData
+ //@F5A can only be true if we are running to v5r2
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ request.setExtendedColumnDescriptorOption((byte)0xF1); //@F5A
+ } //@F5A
+
+ commonPrepareBefore (sqlStatement, request);
+ commonExecuteBefore (sqlStatement, request);
+
+ if (connectReply != null) {
+ connectReply.returnToPool();connectReply = null;
+ }
+ if (normalPrepareReply != null) {
+ normalPrepareReply.returnToPool();normalPrepareReply = null;
+ }
+
+ if (execImmediateReply != null) { execImmediateReply.returnToPool(); execImmediateReply=null;}
+ execImmediateReply = connection_.sendAndReceive (request, id_); //@P0C
+
+ int errorClass = execImmediateReply.getErrorClass();
+ int returnCode = execImmediateReply.getReturnCode();
+
+ DBReplySQLCA sqlca = execImmediateReply.getSQLCA (); //@F10M
+
+ if(errorClass != 0)
+ {
+ positionOfSyntaxError_ = sqlca.getErrd(5); //@F10A
+ if(returnCode < 0)
+ JDError.throwSQLException (connection_, id_, errorClass, returnCode);
+ else
+ postWarning (JDError.getSQLWarning (connection_, id_, errorClass, returnCode));
+ }
+
+ transactionManager_.processCommitOnReturn(execImmediateReply); // @E2A
+
+ cursor_.processCursorAttributes(execImmediateReply); //@cur
+
+ // Compute the update count.
+ //@F10M DBReplySQLCA sqlca = reply.getSQLCA ();
+ updateCount_ = sqlca.getErrd (3); //@F1C
+ rowCountEstimate_ = -1; // @ECA
+
+ //@F5A Don't have to check if a v5r2 system, because extendedMetaData
+ //@F5A can only be true if we are running to v5r2
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ extendedColumnDescriptors_ = execImmediateReply.getExtendedColumnDescriptors (); //@F5A
+ } //@F5A
+
+ //Make an auto-generated key result set if it was requested //@F5A
+ // Note: This should not happen if running to a release after V5R4 as the insert will always be wrapped with a SELECT //@GKA
+ if(autoGeneratedKeys_ == RETURN_GENERATED_KEYS && //@F5A
+ (connection_.getVRM() >= JDUtilities.vrm520)) //@F5A
+ makeGeneratedKeyResultSet(returnCode, sqlca); //@F5A
+ else if(generatedKeys_ != null) //@PDA genkeys - handle previous genkeys
+ {
+ generatedKeys_.close();
+ generatedKeys_ = null;
+ }
+
+ // Compute the number of results.
+ //boolean isCall = (sqlStatement.getNativeType () == JDSQLStatement.TYPE_CALL); //@cur moved above
+ if( /*(numberOfResults_ == 0) && */(isCall))
+ numberOfResults_ = sqlca.getErrd (2); //@F1C
+ else
+ numberOfResults_ = 0;
+
+ // If this is a CALL and result sets came back, but
+ // no format was returned, then open the cursor. The result
+ // set must be forward only and read only.
+ // This is a system restriction. @EBA
+ // As of V5R3, the restriction to be forward only no longer applies @KBA
+ if((isCall == true) && (numberOfResults_ > 0))
+ {
+ boolean preV5R3 = connection_.getVRM() < JDUtilities.vrm530;
+ if (extendedMetaData) { /*@K3A*/
+ cursor_.setExtendedMetaData(extendedMetaData);
+ }
+ JDServerRow row = new JDServerRow (connection_, id_,
+ cursor_.openDescribe (openAttributes, resultSetType_), //@KBA
+ settings_);
+ String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F8A
+
+ JDServerRowCache rowCache = new JDServerRowCache (row, connection_, id_, getBlockingFactor (cursorSensitivity,
+ sqlStatement, row.getRowLength()), false, (preV5R3 ? ResultSet.TYPE_FORWARD_ONLY : resultSetType_), cursor_); //@PDC perf //@pda perf2 - fetch/close
+
+ //if pre-v5r3 create a FORWARD_ONLY RESULT SET
+ if(preV5R3) //@KBA
+ {
+ resultSet_ = new AS400JDBCResultSet (this,
+ sqlStatement, rowCache, connection_.getCatalog(),
+ cursor_.getName(), maxRows_, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, fetchDirection_,
+ fetchSize_);
+ }
+ else //@KBA
+ { //@KBA
+ resultSet_ = new AS400JDBCResultSet (this, //@KBA
+ sqlStatement, rowCache, connection_.getCatalog(), //@KBA
+ cursor_.getName(), maxRows_, resultSetType_, //@KBA
+ ResultSet.CONCUR_READ_ONLY, fetchDirection_, //@KBA
+ fetchSize_); //@KBA
+ }
+
+ if(resultSet_.getConcurrency () != resultSetConcurrency_)
+ postWarning (JDError.getSQLWarning (JDError.WARN_OPTION_VALUE_CHANGED));
+ }
+
+ commonPrepareAfter (sqlStatement, execImmediateReply);
+ commonExecuteAfter (sqlStatement, execImmediateReply);
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request = null;
+ }
+ if (execImmediateReply != null) { execImmediateReply.returnToPool(); execImmediateReply = null; } /*@B5A*/
+ }
+
+ // Inform the transaction manager that a statement
+ // was executed.
+ transactionManager_.statementExecuted ();
+
+ // Output a summary as a trace message. The * signifies that the
+ // statement name comes from the RPB.
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this,
+ "Executed immediately " + name_ + "*, SQL Statement -->[" + sqlStatement + "]");
+ JDTrace.logInformation (this,
+ "Update count = " + updateCount_);
+ JDTrace.logInformation (this,
+ "Result set = " + (resultSet_ != null));
+ JDTrace.logInformation (this,
+ "Number of result sets = " + numberOfResults_);
+ }
+
+ }
+
+ // CASE 3: Normal prepare.
+ //
+ else
+ {
+
+ // Sync up the RPB.
+ syncRPB ();
+
+ DBSQLRequestDS request = null; //@P0A
+ if (normalPrepareReply != null) {
+ normalPrepareReply.returnToPool(); normalPrepareReply = null;
+ } /* B5A */
+ try
+ {
+ int requestedORS = DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_DATA_FORMAT+DBSQLRequestDS.ORS_BITMAP_SQLCA; //@F5A @F10C
+ //@F5A If we are on a system that supports extended column descriptors and if the //@F5A
+ //@F5A user asked for them, send the extended column descriptors code point. //@F5A
+ boolean extendedMetaData = false; //@F5A
+ if(connection_.getVRM() >= JDUtilities.vrm520) //@F5A
+ {
+ //@F5A
+ extendedMetaData = connection_.getProperties().getBoolean(JDProperties.EXTENDED_METADATA); //@F5A
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_EXTENDED_COLUMN_DESCRIPTORS; //@F5A
+ } //@F5A
+ }
+
+ request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_PREPARE_DESCRIBE, id_, requestedORS, 0); //@P0C @F5C
+
+ boolean extended = false; //@540
+ if(connection_.getVRM() >= JDUtilities.vrm540) extended = true; //@540
+ //Bidi-HCG request.setStatementText(sqlStatement.toString(), connection_.unicodeConverter_, extended); //@E3C @P0C @540C
+ request.setStatementText(sqlStatement.toString(), connection_.packageCCSID_Converter, extended);//Bidi-HCG
+ request.setStatementType (sqlStatement.getNativeType ());
+
+ if(packageManager_.isEnabled())
+ {
+ if(sqlStatement.isPackaged())
+ {
+ request.setPrepareOption (1);
+ request.setPackageName (packageManager_.getName (), connection_.converter_); //@P0C
+ }
+ else
+ {
+ request.setPrepareOption (0);
+ request.setPackageName(null, connection_.converter_); //send empty code point
+ }
+ }
+ else
+ request.setPrepareOption (0);
+
+ //@F5A Don't have to check if a v5r2 system, because extendedMetaData
+ //@F5A can only be true if we are running to v5r2
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ request.setExtendedColumnDescriptorOption((byte)0xF1); //@F5A
+ } //@F5A
+
+ commonPrepareBefore (sqlStatement, request);
+ if (execImmediateReply != null) {
+ execImmediateReply.returnToPool();execImmediateReply = null;
+ }
+ if (connectReply != null) {
+ connectReply.returnToPool();connectReply = null;
+ }
+
+ if (normalPrepareReply != null) { normalPrepareReply.returnToPool(); normalPrepareReply=null; }
+ normalPrepareReply = connection_.sendAndReceive (request, id_); //@P0C
+
+ int errorClass = normalPrepareReply.getErrorClass();
+ int returnCode = normalPrepareReply.getReturnCode();
+
+ if(errorClass != 0)
+ {
+ positionOfSyntaxError_ = normalPrepareReply.getSQLCA().getErrd(5); //@F10A
+
+ if(returnCode < 0)
+ JDError.throwSQLException (connection_, id_, errorClass, returnCode);
+ else
+ postWarning (JDError.getSQLWarning (connection_, id_, errorClass, returnCode));
+ }
+
+ // Gather results from the reply.
+ DBDataFormat dataFormat = normalPrepareReply.getDataFormat ();
+ if(dataFormat == null)
+ resultRow = null;
+ else
+ resultRow = new JDServerRow (connection_, id_,
+ dataFormat, settings_);
+
+ //@F5A Don't have to check if a v5r2 system, because extendedMetaData
+ //@F5A can only be true if we are running to v5r2
+ if(extendedMetaData) //@F5A
+ {
+ //@F5A
+ extendedColumnDescriptors_ = normalPrepareReply.getExtendedColumnDescriptors (); //@F5A
+ } //@F5A
+
+ commonPrepareAfter (sqlStatement, normalPrepareReply);
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request=null;
+ }
+ if (normalPrepareReply != null) { normalPrepareReply.returnToPool(); normalPrepareReply = null; } //@B5A
+ }
+
+ // Output a summary as a trace message. The * signifies that the
+ // statement name comes from the RPB.
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this,
+ "Prepared " + name_ + "*, SQL Statement -->[" + sqlStatement + "]");
+ }
+
+ }
+
+ // Check to see if the statement was cancelled.
+ if(cancelled_)
+ JDError.throwSQLException (JDError.EXC_OPERATION_CANCELLED);
+
+ // If any of the fields is a locator, then we need to turn off @B2A
+ // record blocking. @B2A
+ lastPrepareContainsLocator_ = false; // @B2A
+ if(resultRow != null)
+ { // @B2A
+ int fieldCount = resultRow.getFieldCount (); // @B2A
+ for(int i = 1; i <= fieldCount; ++i)
+ { // @B2A
+ SQLData sqlData = resultRow.getSQLData(i);
+ int sqlType = sqlData.getSQLType(); //@xml3
+ if(sqlType == SQLData.CLOB_LOCATOR ||
+ sqlType == SQLData.BLOB_LOCATOR ||
+ sqlType == SQLData.DBCLOB_LOCATOR ||
+ sqlType == SQLData.NCLOB_LOCATOR ||
+ sqlType == SQLData.XML_LOCATOR) //@xml3
+
+ lastPrepareContainsLocator_ = true; // @B2A
+ } // @B2A
+ } // @B2A
+ } finally {
+ /*@D4A*/
+ if (connection_.isQueryTimeoutMechanismCancel()) {
+ endCancelThread();
+ }
+ }
+ return resultRow;
+ }
+
+
+
+ /**
+ Performs common operations needed after a prepare.
+
+ @param sqlStatement The SQL statement.
+ @param reply The prepare reply.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This method is intended to be overriden, if needed.
+ //
+ void commonPrepareAfter (JDSQLStatement sqlStatement,
+ DBReplyRequestedDS reply) // private protected
+ throws SQLException
+ {
+ // Nothing.
+ }
+
+
+
+ /**
+ Performs common operations needed before a prepare.
+
+ @param sqlStatement The SQL statement.
+ @param request The prepare request.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This method is intended to be overriden, if needed.
+ //
+ void commonPrepareBefore (JDSQLStatement sqlStatement,
+ DBSQLRequestDS request) // private protected
+ throws SQLException
+ {
+ // Close the result set before preparing another.
+ closeResultSet (JDCursor.REUSE_YES);
+ }
+
+
+
+ /**
+ Performs common operations in leiu of a prepare.
+
+ @param sqlStatement The SQL statement.
+ @param statementIndex The cached statement index.
+
+ @exception SQLException If an error occurs.
+ **/
+ //
+ // This method is intended to be overriden, if needed.
+ //
+ void commonPrepareBypass (JDSQLStatement sqlStatement,
+ int statementIndex) // private protected
+ throws SQLException
+ {
+ // Nothing.
+ }
+
+
+
+ /**
+ Runs an SQL statement that may return multiple result sets.
+ This closes the current result set and clears warnings before
+ executing the new SQL statement.
+
+ Under some situations, a single SQL statement may return
+ multiple result sets, an update count, or both. This might occur
+ when executing a stored procedure that returns multiple
+ result sets or when dynamically executing an unknown SQL string.
+
+ Use getMoreResults(), getResultSet(), and getUpdateCount()
+ to navigate through multiple result sets, an update count, or
+ both.
+
+ @param sql The SQL statement.
+ @return true if a result set was returned, false
+ if an update count was returned or nothing
+ was returned.
+
+ @exception SQLException If the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, or an error occurs.
+ **/
+ public boolean execute (String sql)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_); // @A1A @G4C
+
+ if(JDTrace.isTraceOn()) // @D0A
+ JDTrace.logInformation (this, "Executing SQL Statement -->[" + sqlStatement + "]"); // @D0A
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ //
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ // if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+
+ return(resultSet_ != null);
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL statement that may return multiple result sets and
+ makes any auto-generated keys available for retrieval using
+ Statement.getGeneratedKeys(). This closes the current result set
+ and clears warnings before executing the new SQL statement.
+
+ Under some situations, a single SQL statement may return
+ multiple result sets, an update count, or both. This might occur
+ when executing a stored procedure that returns multiple
+ result sets or when dynamically executing an unknown SQL string.
+
+ Use getMoreResults(), getResultSet(), and getUpdateCount()
+ to navigate through multiple result sets, an update count, or
+ both.
+
+ This method requires OS/400 V5R2
+ or IBM i. If connecting to OS/400 V5R1 or earlier, an exception
+ will be thrown.
+
+ @param sql The SQL statement.
+ @param autoGeneratedKeys Indicates whether auto-generated keys should be made available for
+ retrieval. Valid values are Statement.RETURN_GENERATED_KEYS and
+ Statement.NO_GENERATED_KEYS.
+ @return true if a result set was returned, false
+ if an update count was returned or nothing
+ was returned.
+
+ @exception SQLException If the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the value for autoGeneratedKeys is
+ not a valid value, if connecting to OS/400 V5R1
+ or earlier, an error occurs.
+ @since Modification 5
+ **/
+
+ public boolean execute (String sql, int autoGeneratedKeys)
+ throws SQLException
+ {
+ if(connection_.getVRM() < JDUtilities.vrm520) //@F5A
+ JDError.throwSQLException(JDError.EXC_FUNCTION_NOT_SUPPORTED); //@F5A
+
+ verifyGeneratedKeysParameter(autoGeneratedKeys);
+ autoGeneratedKeys_ = autoGeneratedKeys;
+
+ if((connection_.getVRM() >= JDUtilities.vrm610) && //@GKA
+ (autoGeneratedKeys_ == RETURN_GENERATED_KEYS)) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ //if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql);
+ //Construct the new JDSQLStatement object
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator(), escapeProcessing_, packageCriteria_, connection_);
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+ sqlStatement.setSelectFromInsert(true);
+ }
+
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+
+ return(resultSet_ != null);
+ }
+ }
+ else //@GKA do what we always have
+ return execute (sql);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL statement that may return multiple result sets and
+ makes any auto-generated keys for the columns indicated in the given array
+ available for retrieval using Statement.getGeneratedKeys().
+ This closes the current result set and clears warnings before
+ executing the new SQL statement.
+
+ Under some situations, a single SQL statement may return
+ multiple result sets, an update count, or both. This might occur
+ when executing a stored procedure that returns multiple
+ result sets or when dynamically executing an unknown SQL string.
+
+ Use getMoreResults(), getResultSet(), and getUpdateCount()
+ to navigate through multiple result sets, an update count, or
+ both.
+
+ This method is not supported when connecting to IBM i V5R4 or earlier systems.
+
+ @param sql The SQL statement.
+ @param columnIndexes Indicates that auto-generated keys for the indicated
+ columns should be made available for retrieval.
+ @return true if a result set was returned, false
+ if an update count was returned or nothing
+ was returned.
+ @exception java.sql.SQLException - If connecting to IBM i V5R4 or earlier systems,
+ if the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the value for columnIndexes is
+ not a valid value, or an error occurs.
+ @since Modification 5
+ **/
+ public boolean execute (String sql, int[] columnIndexes)
+ throws SQLException
+ {
+ if(connection_.getVRM() >= JDUtilities.vrm610) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ // if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ //check if the statement is an insert statement
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql, columnIndexes, null);
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+
+ autoGeneratedKeys_ = RETURN_GENERATED_KEYS; // specify we want generated keys
+ sqlStatement.setSelectFromInsert(true);
+ }
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+
+ return(resultSet_ != null);
+ }
+ }
+ else //@GKA
+ {
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ return false;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL statement that may return multiple result sets and
+ makes any auto-generated keys for the columns indicated in the given array
+ available for retrieval using Statement.getGeneratedKeys().
+ This closes the current result set and clears warnings before
+ executing the new SQL statement.
+
+ Under some situations, a single SQL statement may return
+ multiple result sets, an update count, or both. This might occur
+ when executing a stored procedure that returns multiple
+ result sets or when dynamically executing an unknown SQL string.
+
+ Use getMoreResults(), getResultSet(), and getUpdateCount()
+ to navigate through multiple result sets, an update count, or
+ both.
+
+ This method is not supported when connecting to IBM i V5R4 or earlier systems.
+
+ @param sql The SQL statement.
+ @param columnNames Indicates that auto-generated keys for the indicated
+ columns should be made available for retrieval.
+ @return true if a result set was returned, false
+ if an update count was returned or nothing
+ was returned.
+ @exception java.sql.SQLException - If connecting to IBM i V5R4 or earlier systems,
+ if the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the value for columnNames is
+ not a valid value, or an error occurs.
+ @since Modification 5
+ **/
+ public boolean execute (String sql, String[] columnNames)
+ throws SQLException
+ {
+ if(connection_.getVRM() >= JDUtilities.vrm610) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ // if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ //check if the statement is an insert statement
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql, null, columnNames);
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+
+ sqlStatement.setSelectFromInsert(true);
+ autoGeneratedKeys_ = RETURN_GENERATED_KEYS; // specify we want generated keys
+ }
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+
+ return(resultSet_ != null);
+ }
+ }
+ else // Do what we always have
+ {
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ return false;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Runs the batch of SQL statements. Batch updates can be used
+ to submit a set of SQL statements together as a single unit.
+ The SQL statements are run in the order in which they were
+ added to the batch. The batch is cleared after the SQL statements
+ are run. In addition, this closes the current result set and
+ clears warnings before executing the new SQL statement.
+
+ When batch updates are run, autocommit should usually be turned off.
+ This allows the caller to decide whether or not to commit the
+ transaction in the event that an error occurs and some of the
+ SQL statements in a batch fail to run.
+
+ @return An array of row counts for the SQL statements that are run.
+ The array contains one element for each statement in the
+ batch of SQL statements. The array is ordered according to
+ the order in which the SQL statements were added to the batch.
+
+ @exception SQLException If the statement is not open,
+ an SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, an SQL statement returns
+ a result set, or an error occurs.
+ **/
+ //
+ // Implementation notes:
+ //
+ // 1. We are using a Vector as the main data structure.
+ // Vector is supposedly synchronized already, so we
+ // should not have to worry about synchronization.
+ //
+ public int[] executeBatch ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ if(batch_ == null) batch_ = new Vector(); //@P0A
+ int batchSize = batch_.size ();
+ int[] updateCounts = new int[batchSize];
+
+ int i = 0;
+ try
+ {
+ Enumeration list = batch_.elements ();
+ while(list.hasMoreElements ())
+ {
+
+ // Prepare and execute. Check for a result set in
+ // both places. It is best to catch it after the
+ // prepare (so we don't open a cursor), but with
+ // some stored procedures, we can't catch it until
+ // the execute.
+ JDSQLStatement sqlStatement = (JDSQLStatement) list.nextElement ();
+
+ if(JDTrace.isTraceOn()) // @D0A
+ JDTrace.logInformation (this, "Executing from batch SQL Statement -->[" + sqlStatement + "]"); // @D0A
+
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ if(resultRow != null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ commonExecute (sqlStatement, resultRow);
+ if(resultSet_ != null)
+ {
+ closeResultSet (JDCursor.REUSE_YES);
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+ updateCounts[i++] = updateCount_;
+ }
+ }
+ catch(SQLException e)
+ {
+
+ // The specification says that if we get an error,
+ // then the size of the update counts array should
+ // reflect the number of statements that were
+ // executed without error.
+ int[] updateCounts2 = new int[i];
+ System.arraycopy (updateCounts, 0, updateCounts2, 0, i);
+
+ batch_.removeAllElements ();
+ BatchUpdateException throwException = new BatchUpdateException (e.getMessage (),
+ e.getSQLState (), e.getErrorCode (), updateCounts2);
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+
+ batch_.removeAllElements ();
+ return updateCounts;
+ }
+ }
+
+
+
+ /**
+ Runs an SQL statement that returns a single result set.
+ This closes the current result set and clears warnings
+ before executing the new SQL statement.
+
+ @param sql The SQL statement.
+ @return The result set that contains the data produced
+ by the query.
+
+ @exception SQLException If the statement is not open,
+ the SQL statement contains a syntax
+ error, no result set is returned by the
+ database, the query timeout limit is
+ exceeded, or an error occurs.
+ **/
+ public ResultSet executeQuery (String sql)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_); // @A1A @G4C
+
+ if(JDTrace.isTraceOn()) // @D0A
+ JDTrace.logInformation (this, "Executing query, SQL Statement -->[" + sqlStatement + "]"); // @D0A
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ // if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+
+ if((behaviorOverride_ & 1) == 0) // @F9a
+ {
+ // @F9a
+ if(resultSet_ == null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ // @F9a
+ return resultSet_;
+ }
+ }
+
+
+
+ /**
+ Runs an SQL INSERT, UPDATE, or DELETE statement, or any
+ SQL statement that does not return a result set.
+ This closes the current result set and clears warnings
+ before executing the new SQL statement.
+
+ @param sql The SQL statement.
+ @return Either the row count for INSERT, UPDATE, or
+ DELETE, or 0 for SQL statements that
+ return nothing.
+
+ @exception SQLException If the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the statement returns
+ a result set, or an error occurs.
+ **/
+ public int executeUpdate (String sql)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_); // @A1A @G4A
+
+
+ if(JDTrace.isTraceOn()) // @D0A
+ JDTrace.logInformation (this, "Executing update, SQL Statement -->[" + sqlStatement + "]"); // @D0A
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+ // if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ // Prepare and execute. Check for a result set in both
+ // places. It is best to catch it after the prepare (so
+ // we don't open a cursor), but with some stored procedures,
+ // we can't catch it until the execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ if(resultRow != null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ commonExecute (sqlStatement, resultRow);
+ if(resultSet_ != null)
+ {
+ closeResultSet (JDCursor.REUSE_YES);
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+
+ return updateCount_;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL INSERT, UPDATE, or DELETE statement, or any
+ SQL statement that does not return a result set and
+ makes any auto-generated keys available for retrieval using
+ Statement.getGeneratedKeys().
+ This closes the current result set and clears warnings
+ before executing the new SQL statement.
+ This method requires OS/400 V5R2 or
+ or IBM i. If connecting to OS/400 V5R1 or earlier, an exception
+ will be thrown.
+
+
+ @param sql The SQL statement.
+ @return Either the row count for INSERT, UPDATE, or
+ DELETE, or 0 for SQL statements that
+ return nothing.
+
+ @exception SQLException If the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the statement returns
+ a result set, the value for autoGeneratedKeys is
+ not a valid value, if connecting to OS/400 V5R1
+ or earlier, an error occurs.
+ @since Modification 5
+ **/
+ public int executeUpdate (String sql, int autoGeneratedKeys)
+ throws SQLException
+ {
+ if(connection_.getVRM() < JDUtilities.vrm520) //@F5A
+ JDError.throwSQLException(JDError.EXC_FUNCTION_NOT_SUPPORTED); //@F5A
+
+ verifyGeneratedKeysParameter(autoGeneratedKeys);
+ autoGeneratedKeys_ = autoGeneratedKeys;
+
+ if((connection_.getVRM() >= JDUtilities.vrm610) && //@GKA
+ (autoGeneratedKeys_ == RETURN_GENERATED_KEYS)) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql,
+ settings_.getDecimalSeparator (), escapeProcessing_,
+ packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removed this code let engine return error
+ //
+ //if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql);
+ //Create a new JDSQLStatement
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator(), escapeProcessing_, packageCriteria_, connection_);
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+
+ sqlStatement.setSelectFromInsert(true);
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ commonExecute (sqlStatement, resultRow);
+ }
+ else
+ {
+ // Prepare and execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ if(resultRow != null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ commonExecute (sqlStatement, resultRow);
+ if(resultSet_ != null)
+ {
+ closeResultSet (JDCursor.REUSE_YES);
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ }
+ return updateCount_;
+ }
+ }
+ else //@GKA do what we always have
+ return executeUpdate (sql);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL INSERT, UPDATE, or DELETE statement, or any
+ SQL statement that does not return a result set and
+ makes any auto-generated keys for the columns indicated in the given array
+ available for retrieval using Statement.getGeneratedKeys().
+ This closes the current result set and clears warnings
+ before executing the new SQL statement.
+
+ This method is not supported when connecting to IBM i V5R4 or earlier systems.
+
+ @param sql The SQL statement.
+ @param columnIndexes The indexes of columns for which auto-generated keys should be made
+ available for retrieval.
+ @return Either the row count for INSERT, UPDATE, or
+ DELETE, or 0 for SQL statements that
+ return nothing.
+ @exception SQLException If connection to IBM i V5R4 or earlier systems,
+ the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the statement returns
+ a result set, the value for autoGeneratedKeys is
+ not a valid value or an error occurs.
+
+ @since Modification 5
+ **/
+ public int executeUpdate (String sql, int[] columnIndexes)
+ throws SQLException
+ {
+ if(connection_.getVRM() >= JDUtilities.vrm610) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ //make sure the statement is open
+ checkOpen ();
+
+ //create the sql statement object.
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing update, SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+
+ //if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ //check if the statement is an insert statement
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql, columnIndexes, null);
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+
+ sqlStatement.setSelectFromInsert(true);
+ autoGeneratedKeys_ = RETURN_GENERATED_KEYS; // specify we want generated keys
+ // prepare and execute
+ JDServerRow resultRow = commonPrepare(sqlStatement);
+ commonExecute(sqlStatement, resultRow);
+ }
+ else // treat just like executeUpdate(String sql) was called
+ {
+ // Prepare and execute. Check for a result set in both
+ // places. It is best to catch it after the prepare (so
+ // we don't open a cursor), but with some stored procedures,
+ // we can't catch it until the execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ if(resultRow != null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ commonExecute (sqlStatement, resultRow);
+ if(resultSet_ != null)
+ {
+ closeResultSet (JDCursor.REUSE_YES);
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ }
+ return updateCount_;
+ }
+ }
+ else
+ {
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ return 0;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Runs an SQL INSERT, UPDATE, or DELETE statement, or any
+ SQL statement that does not return a result set and
+ makes any auto-generated keys for the columns indicated in the given array
+ available for retrieval using Statement.getGeneratedKeys().
+ This closes the current result set and clears warnings
+ before executing the new SQL statement.
+
+ This method is not supported when connecting to IBM i V5R4 or earlier systems.
+
+ @param sql The SQL statement.
+ @param columnNames The column names for which auto-generated keys should be made
+ available for retrieval.
+ @return Either the row count for INSERT, UPDATE, or
+ DELETE, or 0 for SQL statements that
+ return nothing.
+ @exception SQLException If connection to IBM i V5R4 or earlier systems,
+ the statement is not open,
+ the SQL statement contains a syntax
+ error, the query timeout limit is
+ exceeded, the statement returns
+ a result set, the value for autoGeneratedKeys is
+ not a valid value or an error occurs.
+ @since Modification 5
+ **/
+ public int executeUpdate (String sql, String[] columnNames)
+ throws SQLException
+ {
+ if(connection_.getVRM() >= JDUtilities.vrm610) //@GKA
+ {
+ synchronized(internalLock_)
+ {
+ //make sure the statement is open
+ checkOpen ();
+
+ //create the sql statement object.
+ JDSQLStatement sqlStatement = new JDSQLStatement (sql, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Executing update, SQL Statement -->[" + sqlStatement + "]");
+
+ // Validate that no parameters are set, since parameters
+ // imply the need for a PreparedStatement.
+ // Note: This code causes problems with some statements with a syntax error.
+ // For example
+ // select * from sysibm.sysdummy1 where 'a = '?'
+ //
+ // Removing this code to allow database engine errors to be returned.
+ //
+
+ //if(sqlStatement.countParameters () > 0)
+ // JDError.throwSQLException (JDError.EXC_PARAMETER_COUNT_MISMATCH);
+ // @AAD
+
+ //check if the statement is an insert statement
+ if(sqlStatement.isInsert_)
+ {
+ String selectStatement = connection_.makeGeneratedKeySelectStatement(sql, null, columnNames);
+ sqlStatement = new JDSQLStatement(selectStatement, settings_.getDecimalSeparator (), escapeProcessing_, packageCriteria_, connection_);
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Generated keys, SQL Statement -->[" + sqlStatement + "]");
+
+ sqlStatement.setSelectFromInsert(true);
+ autoGeneratedKeys_ = RETURN_GENERATED_KEYS; // specify we want generated keys
+ //prepare and execute
+ JDServerRow resultRow = commonPrepare(sqlStatement);
+ commonExecute(sqlStatement, resultRow);
+ }
+ else // treat just like executeUpdate(String sql) was called
+ {
+ // Prepare and execute. Check for a result set in both
+ // places. It is best to catch it after the prepare (so
+ // we don't open a cursor), but with some stored procedures,
+ // we can't catch it until the execute.
+ JDServerRow resultRow = commonPrepare (sqlStatement);
+ if(resultRow != null)
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+
+ commonExecute (sqlStatement, resultRow);
+ if(resultSet_ != null)
+ {
+ closeResultSet (JDCursor.REUSE_YES);
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ }
+ }
+ return updateCount_;
+ }
+ }
+ else
+ {
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ return 0;
+ }
+ }
+
+
+
+ /**
+ Closes the statement if not explicitly closed by the caller.
+
+ @exception Throwable If an error occurs.
+ **/
+ protected void finalize ()
+ throws Throwable
+ {
+ try{
+ if(! isClosed ()) {
+ JDTrace.logInformation (this, "WARNING: Finalizer thread closing statement object.");
+ close ();
+ }
+ }
+ catch(Exception e){
+ //catch any exceptions and don't throw them
+ }
+ super.finalize ();
+ }
+
+
+
+ /**
+ Returns the appropriate blocking factor for the SQL statement.
+
+ @param sqlStatement The SQL statement.
+ @param rowLength The row length.
+ @return The blocking factor (in rows).
+ **/
+ int getBlockingFactor (String cursorSensitivityProperty,
+ JDSQLStatement sqlStatement,
+ int rowLength) // private protected
+ {
+ boolean block = false;
+ boolean useFetchSize = false;
+
+ // Allow blocking for asensitive cursors @H1A
+ int requestDSCursorType = AS400JDBCResultSet.getDBSQLRequestDSCursorType(cursorSensitivityProperty, resultSetType_, resultSetConcurrency_);
+ // Only block if the cursor is not updatable
+ // and no locators are in the result set. @B2A
+ if((cursor_.getConcurrency() != ResultSet.CONCUR_UPDATABLE) // @B2C @EAC
+ && (lastPrepareContainsLocator_ == false)
+ && (requestDSCursorType != DBSQLRequestDS.CURSOR_SCROLLABLE_SENSITIVE) &&
+ (requestDSCursorType != DBSQLRequestDS.CURSOR_NOT_SCROLLABLE_SENSITIVE)) //@KKB we do not want to block if a sensitive cursor is being used
+ { // @B2A
+
+ // Determine if we should block based on the block
+ // criteria and SQL statement characteristics.
+ if(blockCriteria_.equalsIgnoreCase (JDProperties.BLOCK_CRITERIA_NONE))
+ {
+ block = true;
+ useFetchSize = true;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking -- blockCriteria_="+blockCriteria_);
+ }
+ //
+ // The documentation for Statement.setFetchSize() says
+ // that fetchSize is used when the blockSize is 0
+ //
+ } else if (fetchSize_ > 1 && blockSize_ == 0) {
+ block = true;
+ useFetchSize = true;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking -- fetchSize="+fetchSize_);
+ }
+
+ } else if(sqlStatement != null) {
+ if((blockCriteria_.equalsIgnoreCase (JDProperties.BLOCK_CRITERIA_IF_FETCH))
+ && (sqlStatement.isForFetchOnly())) {
+
+ block = true;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking -- blockCriteria_="+blockCriteria_+" and isForFetchOnly");
+ }
+
+ } else if((blockCriteria_.equalsIgnoreCase (JDProperties.BLOCK_CRITERIA_UNLESS_UPDATE))
+ && (! sqlStatement.isForUpdate())) {
+ block = true;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking -- blockCriteria_="+blockCriteria_+" and isForFetchOnly");
+ }
+
+ } else {
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking ="+block+" blockCriteria="+ blockCriteria_);
+ }
+
+ }
+ } else {
+ if(blockCriteria_.equalsIgnoreCase (JDProperties.BLOCK_CRITERIA_UNLESS_UPDATE)) {
+ block = true;
+ } else {
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor(): Blocking ="+block+" blockCriteria="+ blockCriteria_+" sqlStatement is null");
+ }
+ }
+ }
+ } else {
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this,
+ "getBlockingFactor(): Not blocking -- concurrency="+cursor_.getConcurrency()+
+ " lastPrepareContainsLocator_="+lastPrepareContainsLocator_+
+ " requestCursorType="+requestDSCursorType);
+ }
+ }
+
+ // Compute the blocking factor.
+ int blockingFactor;
+ if(block)
+ {
+ if(useFetchSize) {
+ blockingFactor = fetchSize_;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this,
+ "getBlockingFactor: blockFactor taken from fetchSize_");
+ }
+
+ }
+ else
+ {
+ if (rowLength <= 0) {
+ blockingFactor = 1; // Avoid divide by zero -- bug 3119833
+ } else {
+ blockingFactor = (blockSize_ * 1024) / rowLength;
+ if(blockingFactor > 32767) {
+ blockingFactor = 32767;
+ } else if(blockingFactor <= 1) {
+ blockingFactor = 1;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this,
+ "getBlockingFactor: blockFactor is 1: blockSize_="+blockSize_+" rowLength="+rowLength);
+ }
+
+ }
+ }
+ }
+ } else {
+ blockingFactor = 1;
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this,
+ "getBlockingFactor: block=false so blockFactor is 1");
+ }
+ }
+ if(JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, "getBlockingFactor: blockFactor is "+blockingFactor);
+ }
+ return blockingFactor;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the connection for this statement.
+
+ @return The connection for this statement.
+
+ @exception SQLException If an error occurs.
+ **/
+ public Connection getConnection ()
+ throws SQLException
+ {
+ return connection_;
+ }
+
+
+
+ /**
+ Returns the name of the SQL cursor that is used by
+ subsequent statement execute methods.
+
+ @return The cursor name.
+ **/
+ String getCursorName ()
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ return cursor_.getName ();
+ }
+ }
+
+
+
+ //@F3A
+ /**
+ Returns extended column descriptors for this statement.
+ This will be null if the user has the "extended meta data"
+ property set to false (the default).
+
+ @return The extended column descriptors for this statement.
+ **/
+ DBExtendedColumnDescriptors getExtendedColumnDescriptors ()
+ {
+ synchronized(internalLock_)
+ {
+ return extendedColumnDescriptors_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the fetch direction.
+
+ @return The fetch direction.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getFetchDirection ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return fetchDirection_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the fetch size.
+
+ @return The fetch size.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getFetchSize ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return fetchSize_;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Retrieves any auto-generated keys created as a result of executing this Statement object.
+ Currently DB2 for IBM i supports returning only one auto-generated key to the Toolbox JDBC driver
+ -- the key for the last inserted row. Be aware that the generated key returned is not
+ guaranteed to be unique unless a unique constraint is created on the table.
+
+ In order for this method to return auto-generated keys, the statement must be executed on
+ a table with an identity column. For more information about identity columns, Go to the
+ IBM i Information Center, and search on the phrase "identity column".
+
+
+ This method requires OS/400 V5R2 or IBM i. If connecting to OS/400 V5R1 or earlier,
+ an exception will be thrown.
+
+ This method will return null if the user did not request auto-generated keys
+ during the execute of a Statement or during the prepare of a PreparedStatement.
+ This method will also return null if the application has not executed the
+ statement before calling this method.
+
+ This method will return an empty result set if the database did not generate
+ any auto-generated keys when executing the statement.
+
+ @return The ResultSet object containing the auto-generated key(s)
+ generated by the execution of this Statement object, an empty
+ result set if the database did not generate any auto-generated keys,
+ or null if the application did not request auto-generated keys or
+ did not execute the statement before calling this method.
+
+ @exception SQLException If the statement is not open,
+ if connecting to OS/400 V5R1 or earlier,
+ an error occurs.
+ @since Modification 5
+ **/
+ public ResultSet getGeneratedKeys ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ if(connection_.getVRM() < JDUtilities.vrm520) //@F5A
+ {
+ //@F5A
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED); //@F5A
+ return null; //@F5A
+ } //@F5A
+ //Check if open because generated key result set only makes sense if the
+ //Statement is currently open.
+ checkOpen ();
+
+ //@F6 If the user didn't execute the statement yet, throw a function sequence exception.
+ //@F6 If it's just an issue of the database not returning any keys,
+ //@F6 return an empty result set.
+ //@F6 Since we will also have null generated keys if the database did not
+ //@F6 return us any values, return null instead of throwing a function sequence error.
+ //@F6 This matches the behavior of Statement.getResultSet() if no result set was
+ //@F6 created, or getResultSet() is called before executing a statement.
+ //@F6D If we have not made any generated keys yet, a statement must
+ //@F6D not have been executed, so throw a function sequence error.
+ //@F6D if (generatedKeys_ == null)
+ //@F6D JDError.throwSQLException (JDError.EXC_FUNCTION_SEQUENCE);
+
+ return generatedKeys_;
+ }
+ }
+
+
+
+ /**
+ Returns the maximum field size limit for the statement.
+ The maximum field size limit is the maximum amount of data
+ returned for any column value. It applies only to BINARY,
+ VARBINARY, CHAR, and VARCHAR fields. If the limit is exceeded,
+ then the excess data is discarded.
+
+ @return The maximum field size limit (in bytes), or
+ 0 for no limit.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getMaxFieldSize ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return maxFieldSize_;
+ }
+ }
+
+
+
+ /**
+ Returns the maximum rows limit for the statement.
+ The maximum rows limit is the maximum number of rows that a
+ result set can contain. If the limit is exceeded, then the
+ excess rows are dropped.
+
+ @return The maximum rows limit, or 0 for no limit.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getMaxRows ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return maxRows_;
+ }
+ }
+
+
+
+ /**
+ Returns the next result set. This closes the
+ current result set.
+
+ @return true if another result set is available, false
+ if there are no more result sets.
+
+ @exception SQLException If an error occurs.
+ **/
+ public boolean getMoreResults ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ // Initialize.
+ cancelled_ = false;
+ checkOpen ();
+ closeResultSet (JDCursor.REUSE_RESULT_SET);
+
+ // Determine if there more result sets.
+ if(--numberOfResults_ > 0)
+ {
+
+ // Send the data stream.
+ DBSQLRequestDS request = null; //@P0A
+ try
+ {
+ if((connection_.getVRM() >= JDUtilities.vrm610)) {
+ /*@K3A*/
+ int requestedORS = DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_SQLCA+DBSQLRequestDS.ORS_BITMAP_DATA_FORMAT+DBSQLRequestDS.ORS_BITMAP_CURSOR_ATTRIBUTES;
+ boolean extendedMetaData = connection_.getProperties().getBoolean(JDProperties.EXTENDED_METADATA);
+ if (extendedMetaData)
+ {
+ requestedORS = requestedORS + DBSQLRequestDS.ORS_BITMAP_EXTENDED_COLUMN_DESCRIPTORS;
+ }
+
+ request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE, id_, requestedORS, 0); //@cur
+
+ } else {
+ request = DBDSPool.getDBSQLRequestDS(DBSQLRequestDS.FUNCTIONID_OPEN_DESCRIBE, id_, DBSQLRequestDS.ORS_BITMAP_RETURN_DATA+DBSQLRequestDS.ORS_BITMAP_SQLCA+DBSQLRequestDS.ORS_BITMAP_DATA_FORMAT, 0); //@P0C
+ }
+ int openAttributes = cursor_.getOpenAttributes(null, blockCriteria_); // @E1A
+ request.setOpenAttributes(openAttributes); // @E1C
+
+ //Set the cursor scrollability option if V5R3 or higher, prior to V5R3 we can only be forward only.
+ if(connection_.getVRM() >= JDUtilities.vrm530)
+ {
+ String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F8A
+ /* @H1A Use common routine to determine scrollability */
+ request.setScrollableCursorFlag(AS400JDBCResultSet.getDBSQLRequestDSCursorType(cursorSensitivity, resultSetType_, resultSetConcurrency_));
+ }
+
+ if (getMoreResultsReply != null) { getMoreResultsReply.returnToPool(); getMoreResultsReply=null; }
+ getMoreResultsReply = connection_.sendAndReceive (request, id_); //@P0C
+
+ // Gather information from the reply.
+ // DBReplySQLCA sqlca = getMoreResultsReply.getSQLCA ();
+ DBDataFormat dataFormat = getMoreResultsReply.getDataFormat ();
+ if(this instanceof AS400JDBCCallableStatement) // @550A
+ dataFormat.setCSRSData(true); // @550A
+
+ // Check for system errors.
+ int errorClass = getMoreResultsReply.getErrorClass();
+ int returnCode = getMoreResultsReply.getReturnCode();
+
+ if(errorClass != 0)
+ {
+ if(returnCode < 0)
+ JDError.throwSQLException (connection_, id_, errorClass, returnCode);
+ else
+ postWarning (JDError.getSQLWarning (connection_, id_, errorClass, returnCode));
+ }
+
+ // Process a potential cursor conecurrency override. @E1A @EAC
+ cursor_.processConcurrencyOverride(openAttributes, getMoreResultsReply); // @E1A @EAC
+
+ cursor_.processCursorAttributes(getMoreResultsReply); //@cur
+
+ // Note that the cursor was opened.
+ cursor_.setState (false);
+
+ // Compute the result set.
+ JDServerRow row = new JDServerRow (connection_, id_, dataFormat,
+ settings_);
+ String cursorSensitivity = connection_.getProperties().getString(JDProperties.CURSOR_SENSITIVITY); //@F8A
+
+ JDServerRowCache rowCache = new JDServerRowCache (
+ row,
+ connection_, id_,
+ getBlockingFactor (cursorSensitivity,
+ null,
+ row.getRowLength()),
+ false,
+ resultSetType_,
+ cursor_); //@PDC perf //@pda perf2 - fetch/close
+
+ // If the result set concurrency is updatable, check to @E1C
+ // see if the system overrode the cursor type to read only. @E1C
+ // Don't worry about the other direction (system overrides @E1C
+ // from read-only to updatable). @E1C
+ int actualConcurrency = (resultSetConcurrency_ == ResultSet.CONCUR_UPDATABLE) // @E1C
+ ? cursor_.getConcurrency() : resultSetConcurrency_; // @E1C @EAC
+
+ resultSet_ = new AS400JDBCResultSet (this, null,
+ rowCache, connection_.getCatalog(),
+ cursor_.getName(), maxRows_, resultSetType_,
+ actualConcurrency, fetchDirection_,
+ fetchSize_); // @ECC
+ if(resultSet_.getConcurrency () != resultSetConcurrency_)
+ postWarning (JDError.getSQLWarning (JDError.WARN_OPTION_VALUE_CHANGED));
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request = null;
+ }
+ if (getMoreResultsReply != null) { getMoreResultsReply.returnToPool(); getMoreResultsReply = null; }
+ }
+ }
+
+ // Check to see if the statement was cancelled.
+ if(cancelled_)
+ JDError.throwSQLException (JDError.EXC_OPERATION_CANCELLED);
+
+ // @A0A
+ // Added code to set updateCount_ = -1.
+ updateCount_ = -1; // @A0A
+
+ return(resultSet_ != null);
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Returns the next result set. This closes the current result set. This method
+ handles any current ResultSet object(s) according to the instructions specified
+ by the actionOnCurrentResultSet parameter, and returns true if the next result is a
+ ResultSet object.
+
+ @param current What should happen to current ResultSet objects
+ obtained using the method getResultSet. Valid values are
+ CLOSE_CURRENT_RESULT, KEEP_CURRENT_RESULT, and CLOSE_ALL_RESULTS.
+
+ @return Always false because this method is not supported.
+
+ @exception SQLException if DatabaseMetaData.supportsMultipleOpenResults returns false
+ and either Statement.KEEP_CURRENT_RESULT or Statement.CLOSE_ALL_RESULTS are
+ supplied as the argument.
+ @since Modification 5
+ **/
+ public boolean getMoreResults (int current)
+ throws SQLException
+ {
+ if(current == Statement.CLOSE_CURRENT_RESULT) //@forum1
+ return getMoreResults(); //@forum1
+
+ JDError.throwSQLException (JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ return false;
+ }
+
+
+ //@F10A
+ /**
+ Will return the value of the last syntax error that came back from the IBM i system.
+
+ @return The value of the character of the last syntax error from the system,
+ or 0 if no errors occurred or the value is not known.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getPositionOfSyntaxError ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ return positionOfSyntaxError_;
+ }
+ }
+
+
+ /**
+ Returns the query timeout limit for this statement.
+ The query timeout limit is the number of seconds that the
+ driver will wait for an SQL statement to execute.
+
+ @return The query timeout limit (in seconds), or
+ 0 for no limit.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getQueryTimeout ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return queryTimeout_;
+ }
+ }
+
+
+
+ /**
+ Returns the current result set.
+
+ @return The current result set, or null if an update
+ count was returned or there are no more
+ result sets.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public ResultSet getResultSet ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return resultSet_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the result set concurrency to be used for this statement.
+
+ @return The result set concurrency.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getResultSetConcurrency ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return resultSetConcurrency_;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Returns the result set cursor holdability to be used for this statement.
+
+ @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:
+ The cursor name can be used in SQL positioned UPDATE or DELETE
+ statements to identify the current row in the result set generated
+ by this statement. By definition, SQL positioned UPDATEs or
+ DELETEs must be executed by a different statement than the one
+ that generated the result set being used for positioning.
+
+ Cursor names are case sensitive. However, when using a cursor
+ name within other SQL positioned UPDATE or DELETE statements,
+ the cursor name will be uppercased. If you use a cursor name
+ with lowercase characters, you need to enclose it in double
+ quotes when referring to it in other SQL statements.
+
+ @param cursorName The cursor name. If null, a unique
+ default name will be used.
+
+ @exception SQLException If the statement is not open,
+ a result set is open, the cursor
+ name is not unique within the
+ connection, or an error occurs.
+ **/
+ //
+ // Implementation note:
+ //
+ // If you set the cursor name to a mixed case string, and then
+ // later refer to it in an SQL statement, SQL will choke because it
+ // will have uppercased the string.
+ //
+ // At first I thought we should always uppercase, the cursor name
+ // but that limits callers. The better solution is to have the callers
+ // surround mixed case cursor names in SQL statements with double
+ // quotes.
+ //
+ public void setCursorName (String cursorName)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+
+ // Check that no cursor is open for this statement.
+ // We can not just check the cursor, because if the
+ // caller closes the result set, we do not close the
+ // cursor right away.
+ if(resultSet_ != null)
+ {
+ if(! resultSet_.isClosed ())
+ JDError.throwSQLException (JDError.EXC_CURSOR_STATE_INVALID);
+ else
+ closeResultSet (JDCursor.REUSE_YES);
+ }
+
+ // If name is null, then use the default name.
+ if(cursorName == null)
+ cursorName = cursorDefaultName_;
+
+ // Validate the length of the cursor name.
+ int cursorNameLength = cursorName.length(); // @EEA
+ int maxLength = (connection_.getVRM() >= JDUtilities.vrm610) ? MAX_CURSOR_NAME_LENGTH : MAX_CURSOR_NAME_LENGTH_PRE_V6R1; //@550 128 byte cursor name support
+ if((cursorNameLength > maxLength) || (cursorNameLength == 0)) // @EEC @550 changed MAX_CURSOR_NAME_LENGTH to maxLength
+ JDError.throwSQLException (JDError.EXC_CURSOR_NAME_INVALID);
+
+ // If the name is the same as the current cursor name,
+ // then nothing needs to be done. (If we go through
+ // with the change and the cursor name is the same, it
+ // will get flagged as ambiguous).
+ if(! cursorName.equals (cursor_.getName ()))
+ {
+
+ // Check that the cursor name is unique within the
+ // connection.
+ if(connection_.isCursorNameUsed (cursorName))
+ JDError.throwSQLException (JDError.EXC_CURSOR_NAME_AMBIGUOUS);
+
+ cursor_.setName (cursorName);
+
+ // Since we store the cursor name in the RPB, we need
+ // to sync it after a change.
+ rpbSyncNeeded_ = true;
+
+ }
+ }
+ }
+
+
+
+ /**
+ Sets the escape processing mode. When processing escape
+ clauses, the JDBC driver substitutes escape clauses
+ in SQL statements with DB2 for IBM i SQL grammar elements.
+ If escape processing is not needed, then setting the escape
+ processing mode to false improves performance.
+
+ @param escapeProcessing true to process escape clauses;
+ false otherwise. The default
+ is true.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public void setEscapeProcessing (boolean escapeProcessing)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ escapeProcessing_ = escapeProcessing;
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Escape processing", escapeProcessing_);
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Sets the direction in which the rows in a result set will be
+ processed.
+
+ This setting is not used.
+
+ @param fetchDirection The fetch direction for processing rows.
+ Valid values are:
+ This setting only affects statements that meet the criteria
+ specified in the "block criteria" property. The fetch size
+ is only used if the "block size" property is set to "0".
+
+ This setting only takes effect for result sets that are opened
+ after this method has been called. Ideally, this method should be
+ called before the statement is executed.
+
+
+ @param fetchSize 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 zero.
+
+ @exception SQLException If the statement is not open
+ or the input value is not valid.
+ **/
+ public void setFetchSize (int fetchSize)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ if((fetchSize < 0)
+ || ((fetchSize > maxRows_) && (maxRows_ > 0)))
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ checkOpen ();
+ fetchSize_ = fetchSize;
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Fetch size", fetchSize_);
+
+
+ }
+ }
+
+
+
+ /**
+ Sets the maximum field size limit. The maximum field size
+ limit is the maximum amount of data returned for any column
+ value. It applies only to BINARY, VARBINARY, CHAR, and VARCHAR
+ fields. If the limit is exceeded, then the excess data is
+ discarded.
+
+ @param maxFieldSize The maximum field size limit (in bytes) or
+ 0 for no limit. The default is 0.
+
+ @exception SQLException If the statement is not open
+ or the input value is not valid.
+ **/
+ public void setMaxFieldSize (int maxFieldSize)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+
+ // Validate the argument.
+ if(maxFieldSize < 0)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ maxFieldSize_ = maxFieldSize;
+ settings_ = SQLConversionSettings.getConversionSettingsWithMaxFieldSize(settings_,maxFieldSize);
+
+ if (parameterRow_ != null) {
+ parameterRow_.updateSettings(settings_);
+ }
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Max field size", maxFieldSize_);
+ }
+ }
+
+
+
+ /**
+ Sets the maximum rows limit. The maximum rows limit is the
+ maximum number of rows that a result set can contain.
+ If the limit is exceeded, the excess rows are dropped.
+
+
+ @param maxRows The maximum rows limit or 0 for no limit.
+ The default is 0.
+
+ @exception SQLException If the statement is not open
+ or the input value is not valid.
+ **/
+ //
+ // Implementation note:
+ //
+ // We had a debate about what this means with respect to scrollable
+ // result sets. Does it limit the number of rows in the result set,
+ // or the number of rows fetched. I.e., if you set the max rows to
+ // 50, can you successfully do absolute(51)? It is only fetching
+ // 1 row. The answer came back from the JavaSoft people that it
+ // does indeed limit the number of rows in the result set, not
+ // necessarily the number of fetches.
+ //
+ public void setMaxRows (int maxRows)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+
+ // Validate the argument.
+ if(maxRows < 0)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ maxRows_ = maxRows;
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Max rows", maxRows_);
+ }
+ }
+
+
+
+ /**
+ Sets the query timeout limit. The query timeout limit
+ is the number of seconds that the driver will wait for a
+ SQL statement to execute.
+
+ This is implemented using the database query time limit, also
+ known as QQRYTIMLMT. This value specifies the query processing time limit that is
+ compared to the estimated number of elapsed seconds that a query must run. The
+ time limit determines if the database query can start.
+
+ Beginning with Version 6 Release 1 of IBM i, you must have *JOBCTL special authority.
+
+ @param queryTimeout The query timeout limit (in seconds)
+ or 0 for no limit. The default is the job's query timeout limit
+ value unless this method is explicitly called.
+
+ @exception SQLException If the statement is not open
+ or the input value is not valid.
+ **/
+ public void setQueryTimeout (int queryTimeout)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+
+ // Validate the argument.
+ if(queryTimeout < 0)
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ if((queryTimeout_ != queryTimeout) || !queryTimeoutSet_) /*@B2C*/
+ {
+ queryTimeoutSet_ = true; /*@B2A*/
+ queryTimeout_ = queryTimeout;
+
+ // Since we store the query timeout in the RPB, we need
+ // to sync it after a change.
+ rpbSyncNeeded_ = true;
+ rpbQueryTimeoutChanged_ = true; //@EFA
+ }
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Query timeout", queryTimeout_);
+ }
+ }
+
+
+
+ /**
+ Creates or changes the RPB (Request Parameter Block) for the
+ statement.
+
+ @exception SQLException If an error occurs.
+ **/
+ private void syncRPB ()
+ throws SQLException
+ {
+ if(rpbSyncNeeded_)
+ {
+
+ int functionId = rpbCreated_ ? DBSQLRPBDS.FUNCTIONID_CHANGE_RPB
+ : DBSQLRPBDS.FUNCTIONID_CREATE_RPB;
+
+ DBSQLRPBDS request = null; //@P0A
+ try
+ {
+ request = DBDSPool.getDBSQLRPBDS(functionId, id_, 0, 0); //@P0C
+
+ request.setPrepareStatementName (name_, connection_.converter_); //@P0C
+ request.setCursorName (cursor_.getName (), connection_.converter_); //@P0C
+
+ if(packageManager_.isEnabled())
+ request.setLibraryName (packageManager_.getLibraryName (), connection_.converter_); //@P0C
+
+ if(rpbQueryTimeoutChanged_) //@EFA
+ {
+ // Don't set the query timeout in the request if using the cancel query timeout mechanism @D4C
+ if(queryTimeout_ > 0 && !connection_.isQueryTimeoutMechanismCancel())
+ request.setQueryTimeout (queryTimeout_);
+ else
+ request.setQueryTimeout (-1);
+ }
+
+ if(! connection_.getMustSpecifyForUpdate()) // @J3a @J31c
+ {
+ // @J3a
+ if(resultSetConcurrency_ == ResultSet.CONCUR_UPDATABLE) // @J3a
+ request.setOpenAttributes(0x10 + 0x20 + 0x40 + 0x80); // @J3a
+ } // @J3a
+
+ //@F5D Do not need to specify this on the RPB
+ //@F5D Check system level before sending new code point
+ //@F5D if (connection_.getVRM() >= JDUtilities.vrm520) // @F4A
+ //@F5D {
+ //@F5D if (resultSetHoldability_ == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT) // @F4A
+ //@F5D request.setResultSetHoldabilityOption((byte)0xD5); // @F4A
+ //@F5D else if (resultSetHoldability_ == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) // @F4A
+ //@F5D request.setResultSetHoldabilityOption((byte)0xE8); // @F4A
+ //@F5D}
+
+ // @F6A - Send the RPB describe option
+ String rpbDescOpt = connection_.getProperties().getString(JDProperties.DESCRIBE_OPTION);
+ if(null != rpbDescOpt && rpbDescOpt.length() > 0){
+ if(rpbDescOpt.equals(JDProperties.DESCRIBE_OPTION_SYSTEM_NAMES)){
+ request.setDescribeOption(0xE2);
+ } else if(rpbDescOpt.equals(JDProperties.DESCRIBE_OPTION_LONG_NAMES)){
+ request.setDescribeOption(0xD5);
+ }else if(rpbDescOpt.equals(JDProperties.DESCRIBE_OPTION_LABELS)){
+ request.setDescribeOption(0xD3);
+ }
+ }
+
+ connection_.send (request, id_);
+ }
+ catch(DBDataStreamException e)
+ {
+ JDError.throwSQLException (JDError.EXC_INTERNAL, e);
+ }
+ finally
+ { //@P0A
+ if(request != null) {
+ request.returnToPool(); request = null;
+ }
+ }
+
+ rpbCreated_ = true;
+ rpbSyncNeeded_ = false;
+ }
+ }
+
+
+
+ /**
+ Returns the statement name.
+
+ @return The statement name.
+ **/
+ public String toString ()
+ {
+ return name_;
+ }
+
+
+ /**
+ Verifies values for the autoGeneratedKey parameter.
+
+ @param autoGeneratedKeys Valid values are Statement.RETURN_GENERATED_KEYS and
+ Statement.NO_GENERATED_KEYS.
+ @exception SQLException If an error occurs.
+ **/
+ static final void verifyGeneratedKeysParameter (int autoGeneratedKeys)
+ throws SQLException
+ {
+ if((autoGeneratedKeys != NO_GENERATED_KEYS)
+ && (autoGeneratedKeys != RETURN_GENERATED_KEYS))
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Requests that a
+ * The poolable value of a statement is applicable to both internal
+ * statement caches implemented by the driver and external statement caches
+ * implemented by application servers and other applications.
+ *
+ * By default, a
+ * @param poolable requests that the statement be pooled if true and
+ * that the statement not be pooled if false
+ *
+ * @throws SQLException if the
+ */
+ public void setPoolable(boolean poolable) throws SQLException
+ {
+ checkOpen();//@pda do same as native
+ isPoolable_ = poolable;
+ }
+
+ //@PDA jdbc40
+ /**
+ * Returns the value of the statements poolable hint, indicating whether
+ * pooling of the statement is requested.
+ *
+ * @return The value of the statements poolable hint.
+ *
+ * @throws SQLException if the
+ * see java.sql.Statement#setPoolable(boolean) setPoolable(boolean)
+ */
+ public boolean isPoolable() throws SQLException
+ {
+ checkOpen();//@pda do same as native
+ return isPoolable_;
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCStatement", "java.sql.Statement" };
+ }
+
+ // @D7A
+ /**
+ * Specifies that this Statement will be closed when all its dependent result sets are closed.
+ * If execution of the Statement does not produce any result sets, this method has no effect.
+ * Note: Multiple calls to closeOnCompletion do not toggle the effect on this Statement.
+ * However, a call to closeOnCompletion does effect both the subsequent execution of statements,
+ * and statements that currently have open, dependent, result sets.
+ * @throws SQLException - if this method is called on a closed Statement
+ */
+
+ public void closeOnCompletion() throws SQLException {
+ checkOpen();
+ closeOnCompletion_ = true;
+ }
+/**
+ * Returns a value indicating whether this Statement will be closed when all its dependent result sets are closed.
+ * @return true if the Statement will be closed when all of its dependent result sets are closed; false otherwise
+ * @throws SQLException - if this method is called on a closed Statement
+ */
+
+ // @D7A
+ public boolean isCloseOnCompletion() throws SQLException {
+ checkOpen();
+ return closeOnCompletion_;
+ }
+
+ /*@D4A*/
+ /**
+ Handles the work involved in supporting a setQueryTimeout option with the cancel property set. .
+
+ **/
+ protected void startCancelThread()
+ {
+ // Start a cancel thread if there is a query running and a timeout value has been
+ // specified.
+ if (queryTimeoutSet_ && queryTimeout_ != 0) {
+
+ // We only are going to allow the query timeout to effect queries.
+ // Set a flag that a query is running.
+
+
+ queryRunning_ = true;
+
+ // Create a thread to do the cancel if needed. Start the thread.
+ cancelThread_ = new AS400JDBCQueryCancelThread(this);
+
+ // Uncommented this @A7A ..
+ // this is needed to prevent job from hanging if the extra threads
+ // we started don't end.
+ //
+ cancelThread_.setDaemon(true);
+
+ cancelThread_.start();
+ }
+ }
+
+
+
+ /*@D4A*/
+ /**
+ * endTheCancelThread
+ **/
+ protected void endCancelThread()
+ {
+ // Deal with the cancel thread at this point.
+ if (queryTimeout_ != 0) {
+
+ // Set the flag saying the query is no longer running.
+ queryRunning_ = false;
+
+ // Detach the thread from the statement.
+ cancelThread_.statement_ = null;
+
+ // Interrupt the thread so that it wakes up and dies.
+ cancelThread_.interrupt();
+ }
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCWriter.java b/jdbc40/com/ibm/as400/access/AS400JDBCWriter.java
new file mode 100644
index 000000000..a87c6c637
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCWriter.java
@@ -0,0 +1,185 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCWriter.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.Writer;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+
+/**
+The AS400JDBCWriter class provides a stream
+to write into large objects. The data is valid only within the current
+transaction. Users get one of these objects by calling Clob.setCharacterStream()
+which returns an object of type Writer.
+**/
+class AS400JDBCWriter extends Writer
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+
+ private boolean closed_ = false; // is the stream closed?
+ private long position_; // position from which the user wanted us to start writing
+ private AS400JDBCClob clob_; // We have separate vars for clob and locator to remove build dependency on JDBC 3.0.
+ private AS400JDBCClobLocator locator_;
+ private AS400JDBCSQLXML xml_; //@pda jdbc40
+
+
+ AS400JDBCWriter(AS400JDBCClob clob, long positionToStartWriting)
+ {
+ clob_ = clob;
+ position_ = positionToStartWriting;
+ }
+
+
+ AS400JDBCWriter(AS400JDBCClobLocator locator, long positionToStartWriting)
+ {
+ locator_ = locator;
+ position_ = positionToStartWriting;
+ }
+
+ //@pda jdbc40
+ AS400JDBCWriter(AS400JDBCSQLXML xml, long positionToStartWriting)
+ {
+ xml_ = xml;
+ position_ = positionToStartWriting;
+ }
+
+
+
+
+ /*
+ Close the writer.
+ */
+ public void close()
+ {
+ closed_ = true;
+ }
+
+
+ /*
+ Flush the writer.
+ */
+ public void flush()
+ {
+ //no-op
+ }
+
+
+
+ /*
+ Write a character array to the writer.
+
+ @param cbuf The character byte array the user wants written to the writer.
+ */
+ public void write(char[] cbuf) throws IOException
+ {
+ if (cbuf == null) throw new NullPointerException("cbuf");
+
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ write(cbuf, 0, cbuf.length);
+ }
+
+
+
+ /*
+ Write a character array to the writer from offset off for len characters.
+
+ @param cbuf The character array the user wants written to the writer.
+ @param off The offset into the character array that the user wants written to the
+ writer (1-based).
+ @param len The number of bytes the user wants written to the writer
+ from the byte array they passed in.
+ */
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ if (cbuf == null) throw new NullPointerException("cbuf");
+ if ((off < 0) || (off > len)) throw new ExtendedIllegalArgumentException("off", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ if (len < 0) throw new ExtendedIllegalArgumentException("len", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ write(new String(cbuf, off, len));
+ }
+
+
+
+ /*
+ Write a character to the writer.
+
+ @param cbuf The character the user wants written to the writer.
+ */
+ public void write(int c) throws IOException
+ {
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ write(new String(new char[] { (char)c}));
+ }
+
+
+
+ /*
+ Write a String to the writer from offset off for len characters.
+
+ @param str The string the user wants written to the writer.
+ */
+ public void write(String str) throws IOException
+ {
+ if (str == null) throw new NullPointerException("str");
+
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ write(str, 0, str.length());
+ }
+
+
+
+ /*
+ Write a String to the writer from offset off for len characters.
+
+ @param str The String the user wants written to the writer.
+ @param off The offset into the character array that the user wants written to the
+ writer.
+ @param len The number of bytes the user wants written to the writer
+ from the byte array they passed in.
+ */
+ public synchronized void write(String str, int off, int len) throws IOException
+ {
+ if (str == null) throw new NullPointerException("str");
+ if ((off < 0) || (off > len)) throw new ExtendedIllegalArgumentException("off", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ if (len < 0) throw new ExtendedIllegalArgumentException("len", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+
+ if (closed_) throw new ExtendedIOException(ExtendedIOException.RESOURCE_NOT_AVAILABLE);
+
+ try
+ {
+ if (clob_ != null) clob_.setString(position_, str, off, len);
+ else if (locator_ != null) locator_.setString(position_, str, off, len); //@PDC jdbc40
+ else if (xml_ != null ) xml_.setString(position_, str, off, len); //@PDA jdbc40
+ position_ += len;
+ }
+ catch (SQLException e)
+ {
+ if (JDTrace.isTraceOn()) e.printStackTrace(DriverManager.getLogWriter());
+ closed_ = true;
+ IOException throwException = new IOException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCXADataSource.java b/jdbc40/com/ibm/as400/access/AS400JDBCXADataSource.java
new file mode 100644
index 000000000..7125ecc3f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCXADataSource.java
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCXADataSource.java
+//
+// The source code contained herein is licensed under the IBM Public License
+// Version 1.0, which has been approved by the Open Source Initiative.
+// Copyright (C) 1997-2010 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.sql.SQLException;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+
+
+/**
+The AS400JDBCXADataSource class represents a factory for
+AS400JDBCXAConnection objects.
+
+
+This support is only available when connecting to systems running OS/400 V5R1 or later, or IBM i.
+
+ The following example creates an AS400JDBCXADataSource
+object and creates a connection to the database.
+
+
+ * 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.
+ */
+ public boolean isValid(int timeout) throws SQLException
+ {
+ Object[] oa = new Object[] {new Integer(timeout)};
+ return ((Boolean)callMethodRtnObj("isValid", new Class[] {Integer.TYPE}, oa)).booleanValue();
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the value of the client info property specified by name to the
+ * value specified by value.
+ *
+ * Applications may use the
+ * 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
+ * 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 */
+ {
+ try
+ {
+ callMethod("setClientInfo",
+ new Class[] { String.class, String.class },
+ new Object[] { name, value });
+ } catch (SQLException e)
+ {
+/* ifdef JDBC40 */
+ //may be SQLException or SQLClientInfoException
+ if(e instanceof SQLClientInfoException)
+ throw (SQLClientInfoException)e;
+ else
+ {
+ //HashMap
+ * If an error occurs in setting any of the client info properties, a
+ *
+ * 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 */
+ {
+ try
+ {
+ callMethod ("setClientInfo",
+ new Class[] { Properties.class },
+ new Object[] { properties });
+ }catch(SQLException e)
+ {
+/* ifdef JDBC40 */
+ //may be SQLException or SQLClientInfoException
+ if(e instanceof SQLClientInfoException)
+ throw (SQLClientInfoException)e;
+ else
+ {
+ //create Map
+ * Applications may use the
+ * 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
+ {
+ return (String) callMethodRtnObj("getClientInfo",
+ new Class[] { String.class },
+ new Object[] { 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
+ * @throws SQLException if the database server returns an error when
+ * fetching the client info values from the database
+ */
+ public Properties getClientInfo() throws SQLException
+ {
+ return (Properties) callMethodRtnObj("getClientInfo");
+ }
+
+ //@PDA jdbc40
+ /**
+ * Constructs an object that implements the Note: Since this method is not defined in the JDBC Connection interface,
+ you typically need to cast a Connection object to JDConnectionProxy in order
+ to call this method:
+
+ * 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
+ {
+ return actualConnection_.isValid(timeout);
+ }
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ * Sets the value of the client info property specified by name to the
+ * value specified by value.
+ *
+ * Applications may use the
+ * 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
+ *
+ * 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 */
+ {
+ ((AS400JDBCConnection)actualConnection_).setClientInfo(name, value);
+ }
+
+ // @PDA jdbc40
+ /**
+ * Sets the value of the connection's client info properties. The
+ *
+ * If an error occurs in setting any of the client info properties, a
+ *
+ *
+ * The following client info properties are supported in Toobox for Java.
+ *
+ *
+ *
+ * @param properties
+ * the list of client info properties to set
+ *
+ * @throws ClientInfoException
+ * 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 */
+ {
+ ((AS400JDBCConnection)actualConnection_).setClientInfo(properties);
+ }
+
+ //@PDA jdbc40
+ /**
+ * 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
+ *
+ * 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
+ {
+ return ((AS400JDBCConnection)actualConnection_).getClientInfo(name);
+ }
+
+ //@PDA jdbc40
+ /**
+ * 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
+ * @throws SQLException if the database server returns an error when
+ * fetching the client info values from the database
+ */
+ public Properties getClientInfo() throws SQLException
+ {
+ return ((AS400JDBCConnection)actualConnection_).getClientInfo();
+ }
+
+ //@PDA jdbc40
+ /**
+ * Constructs an object that implements the The JDParameterMetaDataProxy class gets information about the types and properties of the parameters
+in a PreparedStatement object.
+**/
+class JDParameterMetaDataProxy
+extends AbstractProxyImpl
+implements ParameterMetaData
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+
+ // Private data.
+
+ JDConnectionProxy jdConnection_;
+ // The associated JDBC Connection object.
+
+
+
+ public JDParameterMetaDataProxy (JDConnectionProxy jdConnection)
+ {
+ jdConnection_ = jdConnection;
+ }
+
+ // Call a method, and return a 'raw' ProxyReturnValue.
+ private ProxyReturnValue callMethodRtnRaw (String methodName,
+ int argValue)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) });
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a String.
+ private String callMethodRtnStr (String methodName, int argValue)
+ throws SQLException
+ {
+ try {
+ return (String) connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) })
+ .getReturnValue ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return an int.
+ private int callMethodRtnInt (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsInt (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public int getParameterCount()
+ throws SQLException
+ {
+ return callMethodRtnInt("getParameterCount");
+ }
+
+ public int isNullable(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isNullable", param).getReturnValueInt();
+ }
+
+ public boolean isSigned(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isSigned", param).getReturnValueBoolean();
+ }
+
+ public int getPrecision(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getPrecision", param).getReturnValueInt();
+ }
+
+ public int getScale(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getScale", param).getReturnValueInt();
+ }
+
+ public int getParameterType(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getParameterType", param).getReturnValueInt();
+ }
+
+ public String getParameterTypeName(int param)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getParameterTypeName", param);
+ }
+
+ public String getParameterClassName(int param)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getParameterClassName", param);
+ }
+
+ public int getParameterMode(int param)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getParameterMode", param).getReturnValueInt();
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.ParameterMetaData" };
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDPreparedStatementProxy.java b/jdbc40/com/ibm/as400/access/JDPreparedStatementProxy.java
new file mode 100644
index 000000000..43e957db6
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDPreparedStatementProxy.java
@@ -0,0 +1,1081 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDPreparedStatementProxy.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.lang.reflect.InvocationTargetException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+
+
+class JDPreparedStatementProxy
+extends JDStatementProxy
+implements PreparedStatement
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+ // Copied from JDError:
+
+
+ private final static String NOT_SERIALIZABLE = "Parameter is not serializable.";
+
+
+ public JDPreparedStatementProxy (JDConnectionProxy jdConnection)
+ {
+ super (jdConnection);
+ }
+
+
+// JDBC 2.0
+ public void addBatch ()
+ throws SQLException
+ {
+ callMethod ("addBatch");
+ }
+
+
+
+ public void clearParameters ()
+ throws SQLException
+ {
+ callMethod ("clearParameters");
+ }
+
+
+ public boolean execute ()
+ throws SQLException
+ {
+ cachedResultSet_ = null;
+ return callMethodRtnBool ("execute");
+ }
+
+
+ public ResultSet executeQuery ()
+ throws SQLException
+ {
+ cachedResultSet_ = null;
+ try {
+ JDResultSetProxy newResultSet = new JDResultSetProxy (jdConnection_, this);
+ cachedResultSet_ = (JDResultSetProxy) connection_.callFactoryMethod (
+ pxId_, "executeQuery", newResultSet);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ return cachedResultSet_;
+ }
+
+
+
+ public int executeUpdate ()
+ throws SQLException
+ {
+ cachedResultSet_ = null;
+ return callMethodRtnInt ("executeUpdate");
+ }
+
+
+
+// JDBC 2.0
+ public ResultSetMetaData getMetaData ()
+ throws SQLException
+ {
+ try {
+ JDResultSetMetaDataProxy newMetaData = new JDResultSetMetaDataProxy (jdConnection_);
+ return (JDResultSetMetaDataProxy) connection_.callFactoryMethod (
+ pxId_, "getMetaData", newMetaData);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 3.0
+ public ParameterMetaData getParameterMetaData ()
+ throws SQLException
+ {
+ // Avoid dragging in JDError
+ //@K1D throw new SQLException (
+ //@K1D AS400JDBCDriver.getResource("JD" + EXC_FUNCTION_NOT_SUPPORTED),
+ //@K1D EXC_FUNCTION_NOT_SUPPORTED, -99999);
+ try { //@K1A
+ JDParameterMetaDataProxy newMetaData = new JDParameterMetaDataProxy (jdConnection_);
+ return (JDParameterMetaDataProxy) connection_.callFactoryMethod (pxId_, "getParameterMetaData", newMetaData);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+
+// JDBC 2.0
+ public void setArray (int parameterIndex, Array parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setArray",
+ new Class[] { Integer.TYPE, Array.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setAsciiStream (int parameterIndex,
+ InputStream parameterValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (parameterValue == null ||
+ parameterValue instanceof Serializable)
+ iStream = parameterValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (parameterValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Integer (length) });
+ }
+
+
+
+ public void setBigDecimal (int parameterIndex, BigDecimal parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBigDecimal",
+ new Class[] { Integer.TYPE, BigDecimal.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setBinaryStream (int parameterIndex,
+ InputStream parameterValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (parameterValue == null ||
+ parameterValue instanceof Serializable)
+ iStream = parameterValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (parameterValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Integer (length) });
+ }
+
+
+
+// JDBC 2.0
+ public void setBlob (int parameterIndex, Blob parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setBlob",
+ new Class[] { Integer.TYPE, Blob.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setBoolean (int parameterIndex, boolean parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBoolean",
+ new Class[] { Integer.TYPE, Boolean.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Boolean (parameterValue) });
+ }
+
+
+
+ public void setByte (int parameterIndex, byte parameterValue)
+ throws SQLException
+ {
+ callMethod ("setByte",
+ new Class[] { Integer.TYPE, Byte.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Byte (parameterValue) });
+ }
+
+
+
+ public void setBytes (int parameterIndex, byte[] parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBytes",
+ new Class[] { Integer.TYPE, byte[].class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+// JDBC 2.0
+ public void setCharacterStream (int parameterIndex,
+ Reader parameterValue,
+ int length)
+ throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (parameterValue == null)
+ reader = null;
+ else
+ reader = new SerializableReader (parameterValue, Math.max(0,length));
+ callMethod ("setCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ reader,
+ new Integer (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+
+// JDBC 2.0
+ public void setClob (int parameterIndex, Clob parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setClob",
+ new Class[] { Integer.TYPE, Clob.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setDate (int parameterIndex, Date parameterValue)
+ throws SQLException
+ {
+ callMethod ("setDate",
+ new Class[] { Integer.TYPE, Date.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+// JDBC 2.0
+ public void setDate (int parameterIndex,
+ Date parameterValue,
+ Calendar calendar)
+ throws SQLException
+ {
+ callMethod ("setDate",
+ new Class[] { Integer.TYPE, Date.class,
+ Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue,
+ calendar });
+ }
+
+
+
+ public void setDouble (int parameterIndex, double parameterValue)
+ throws SQLException
+ {
+ callMethod ("setDouble",
+ new Class[] { Integer.TYPE, Double.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Double (parameterValue) });
+ }
+
+
+
+ public void setFloat (int parameterIndex, float parameterValue)
+ throws SQLException
+ {
+ callMethod ("setFloat",
+ new Class[] { Integer.TYPE, Float.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Float (parameterValue) });
+ }
+
+
+
+ public void setInt (int parameterIndex, int parameterValue)
+ throws SQLException
+ {
+ callMethod ("setInt",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (parameterValue) });
+ }
+
+
+
+ public void setLong (int parameterIndex, long parameterValue)
+ throws SQLException
+ {
+ callMethod ("setLong",
+ new Class[] { Integer.TYPE, Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Long (parameterValue) });
+ }
+
+
+
+ public void setNull (int parameterIndex, int sqlType)
+ throws SQLException
+ {
+ callMethod ("setNull",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (sqlType) });
+ }
+
+
+ public void setNull (int parameterIndex, int sqlType, String typeName)
+ throws SQLException
+ {
+ callMethod ("setNull",
+ new Class[] { Integer.TYPE, Integer.TYPE,
+ String.class },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (sqlType),
+ typeName});
+ }
+
+ public void setObject (int parameterIndex, Object parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { Integer.TYPE, Object.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setObject (int parameterIndex,
+ Object parameterValue,
+ int sqlType)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { Integer.TYPE, Object.class,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue,
+ new Integer (sqlType) });
+ }
+
+
+
+ public void setObject (int parameterIndex,
+ Object parameterValue,
+ int sqlType,
+ int scale)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { Integer.TYPE, Object.class,
+ Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue,
+ new Integer (sqlType),
+ new Integer (scale) });
+ }
+
+
+
+// JDBC 2.0
+ public void setRef (int parameterIndex, Ref parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setRef",
+ new Class[] { Integer.TYPE, Ref.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setShort (int parameterIndex, short parameterValue)
+ throws SQLException
+ {
+ callMethod ("setShort",
+ new Class[] { Integer.TYPE, Short.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Short (parameterValue) });
+ }
+
+
+
+ public void setString (int parameterIndex, String parameterValue)
+ throws SQLException
+ {
+ callMethod ("setString",
+ new Class[] { Integer.TYPE, String.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+ public void setTime (int parameterIndex, Time parameterValue)
+ throws SQLException
+ {
+ callMethod ("setTime",
+ new Class[] { Integer.TYPE, Time.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+// JDBC 2.0
+ public void setTime (int parameterIndex,
+ Time parameterValue,
+ Calendar calendar)
+ throws SQLException
+ {
+ callMethod ("setTime",
+ new Class[] { Integer.TYPE, Time.class,
+ Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue, calendar });
+ }
+
+
+
+ public void setTimestamp (int parameterIndex, Timestamp parameterValue)
+ throws SQLException
+ {
+ callMethod ("setTimestamp",
+ new Class[] { Integer.TYPE, Timestamp.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+
+// JDBC 2.0
+ public void setTimestamp (int parameterIndex,
+ Timestamp parameterValue,
+ Calendar calendar)
+ throws SQLException
+ {
+ callMethod ("setTimestamp",
+ new Class[] { Integer.TYPE, Timestamp.class,
+ Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ parameterValue, calendar });
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use setCharacterStream(int, Reader, int) instead.
+@see #setCharacterStream
+**/
+ public void setUnicodeStream (int parameterIndex,
+ InputStream parameterValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (parameterValue == null ||
+ parameterValue instanceof Serializable)
+ iStream = parameterValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (parameterValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setUnicodeStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Integer (length) });
+ }
+
+
+// JDBC 3.0
+ public void setURL (int parameterIndex,
+ URL parameterValue)
+ throws SQLException
+ {
+ callMethod ("setURL",
+ new Class[] { Integer.TYPE, URL.class},
+ new Object[] { new Integer (parameterIndex),
+ parameterValue });
+ }
+
+
+/* ifdef JDBC40 */
+ //@PDA jdbc40
+ public void setRowId(int parameterIndex, RowId x) throws SQLException
+ {
+ callMethod ("setRowId",
+ new Class[] { Integer.TYPE, RowId.class},
+ new Object[] { new Integer (parameterIndex), x });
+ }
+/* endif */
+
+ //@PDA jdbc40
+ public void setNString(int parameterIndex, String value) throws SQLException
+ {
+ callMethod ("setNString",
+ new Class[] { Integer.TYPE, String.class },
+ new Object[] { new Integer (parameterIndex), value });
+ }
+
+ //@PDA jdbc40
+ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (value == null)
+ reader = null;
+ else
+ reader = new SerializableReader (value, (int) Math.max(0,length));
+ callMethod ("setNCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ reader,
+ new Long(length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public void setNClob(int parameterIndex, NClob value) throws SQLException
+ {
+ if (value != null &&
+ !(value instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setNClob",
+ new Class[] { Integer.TYPE, NClob.class },
+ new Object[] { new Integer (parameterIndex),
+ value });
+ }
+/* endif */
+
+ //@PDA jdbc40
+ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader, (int) Math.max(0,length));
+ callMethod ("setClob",
+ new Class[] { Integer.TYPE, Reader.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ serialRreader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (inputStream == null ||
+ inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBlob",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader, (int) Math.max(0,length));
+ callMethod ("setNClob",
+ new Class[] { Integer.TYPE, Reader.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ serialRreader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
+ {
+ if (xmlObject != null &&
+ !(xmlObject instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setSQLXML",
+ new Class[] { Integer.TYPE, SQLXML.class },
+ new Object[] { new Integer (parameterIndex),
+ xmlObject });
+ }
+/* endif */
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.PreparedStatement" };
+ }
+
+
+ //@PDA jdbc40
+ public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (reader == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (reader, (int)Math.max(0,length));
+ callMethod ("setCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class,
+ Long.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ serialReader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (parameterIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (parameterIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
+ {
+ InputStream iStream;
+ if (inputStream == null ||
+ inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBlob",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (parameterIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (reader == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (reader);
+ callMethod ("setCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (parameterIndex),
+ serialReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void setClob(int parameterIndex, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (reader == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (reader);
+ callMethod ("setClob",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (parameterIndex),
+ serialReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (value == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (value);
+ callMethod ("setNCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (parameterIndex),
+ serialReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (reader == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (reader);
+ callMethod ("setNClob",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (parameterIndex),
+ serialReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ public void setDBDefault(int parameterIndex) throws SQLException
+ {
+ setDB2Default(parameterIndex);
+ }
+
+ public void setDB2Default(int parameterIndex) throws SQLException {
+ callMethod("setDB2Default",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (parameterIndex)});
+ }
+
+ public void setDB2Unassigned(int parameterIndex) throws SQLException {
+ callMethod("setDB2Unassigned",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (parameterIndex)});
+ }
+
+ public void setDBUnassigned(int parameterIndex) throws SQLException
+ {
+ setDB2Unassigned(parameterIndex); //2 is unassigned
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDResultSetMetaDataProxy.java b/jdbc40/com/ibm/as400/access/JDResultSetMetaDataProxy.java
new file mode 100644
index 000000000..574cf3c6f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDResultSetMetaDataProxy.java
@@ -0,0 +1,261 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDResultSetMetaDataProxy.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.lang.reflect.InvocationTargetException;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+
+
+/**
+ The JDResultSetMetaDataProxy class describes the
+columns in a result set.
+**/
+class JDResultSetMetaDataProxy
+extends AbstractProxyImpl
+implements ResultSetMetaData
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+ // Private data.
+
+ JDConnectionProxy jdConnection_;
+ // The associated JDBC Connection object.
+
+
+
+ public JDResultSetMetaDataProxy (JDConnectionProxy jdConnection)
+ {
+ jdConnection_ = jdConnection;
+ }
+
+ // Call a method, and return a 'raw' ProxyReturnValue.
+ private ProxyReturnValue callMethodRtnRaw (String methodName,
+ int argValue)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) });
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a String.
+ private String callMethodRtnStr (String methodName, int argValue)
+ throws SQLException
+ {
+ try {
+ return (String) connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) })
+ .getReturnValue ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public String getCatalogName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getCatalogName", columnIndex);
+ }
+
+
+// JDBC 2.0
+ public String getColumnClassName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getColumnClassName", columnIndex);
+ }
+
+
+ public int getColumnCount ()
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsInt (pxId_, "getColumnCount");
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public int getColumnDisplaySize (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getColumnDisplaySize", columnIndex)
+ .getReturnValueInt ();
+ }
+
+ public String getColumnLabel (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getColumnLabel", columnIndex);
+ }
+
+
+ public String getColumnName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getColumnName", columnIndex);
+ }
+
+
+ public int getColumnType (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getColumnType", columnIndex)
+ .getReturnValueInt ();
+ }
+
+
+ public String getColumnTypeName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getColumnTypeName", columnIndex);
+ }
+
+
+ public int getPrecision (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getPrecision", columnIndex)
+ .getReturnValueInt ();
+ }
+
+
+ public int getScale (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getScale", columnIndex)
+ .getReturnValueInt ();
+ }
+
+
+ public String getSchemaName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getSchemaName", columnIndex);
+ }
+
+
+ public String getTableName (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnStr ("getTableName", columnIndex);
+ }
+
+
+ public boolean isAutoIncrement (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isAutoIncrement", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isCaseSensitive (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isCaseSensitive", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isCurrency (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isCurrency", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isDefinitelyWritable (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isDefinitelyWritable", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public int isNullable (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isNullable", columnIndex)
+ .getReturnValueInt ();
+ }
+
+
+ public boolean isReadOnly (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isReadOnly", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isSearchable (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isSearchable", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isSigned (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isSigned", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ public boolean isWritable (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("isWritable", columnIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+ // This method is not required by java.sql.ResultSetMetaData,
+ // but it is used by the JDBC testcases, and is implemented
+ // in the public class.
+ public String toString ()
+ {
+ try {
+ return (String) connection_.callMethodReturnsObject (pxId_,
+ "toString");
+ }
+ catch (InvocationTargetException e) {
+ throw ProxyClientConnection.rethrow (e);
+ }
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.ResultSetMetaData" }; //@pdc user cannot cast to AS400JDBCResultSetMetaData
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDResultSetProxy.java b/jdbc40/com/ibm/as400/access/JDResultSetProxy.java
new file mode 100644
index 000000000..b9668a32d
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDResultSetProxy.java
@@ -0,0 +1,2544 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDResultSetProxy.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.InputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+
+class JDResultSetProxy
+extends AbstractProxyImpl
+implements ResultSet
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+ // Private data.
+
+ private JDConnectionProxy jdConnection_;
+ // The object that caused this object to be created.
+
+ private JDStatementProxy cachedStatement_;
+
+ private final static String NOT_SERIALIZABLE = "Parameter is not serializable.";
+
+
+/*---------------------------------------------------------*/
+/* */
+/* MISCELLANEOUS METHODS. */
+/* */
+/*---------------------------------------------------------*/
+
+
+ public JDResultSetProxy (JDConnectionProxy jdConnection)
+ {
+ jdConnection_ = jdConnection;
+ }
+
+
+ public JDResultSetProxy (JDConnectionProxy jdConnection,
+ JDStatementProxy statement)
+ {
+ jdConnection_ = jdConnection;
+ cachedStatement_ = statement;
+ }
+
+
+ // Call a method. No return value is expected.
+ private void callMethod (String methodName)
+ throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ private void callMethod (String methodName,
+ Class[] argClasses,
+ Object[] argValues)
+ throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, methodName, argClasses, argValues);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a boolean.
+ private boolean callMethodRtnBool (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsBoolean (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ private JDInputStreamProxy callMethodRtnInpStrm (String methodName,
+ int argValue)
+ throws SQLException
+ {
+ try {
+ JDInputStreamProxy newStream = new JDInputStreamProxy ();
+ return (JDInputStreamProxy) connection_.callFactoryMethod (
+ pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) },
+ newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return an int.
+ private int callMethodRtnInt (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsInt (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return an Object.
+ private Object callMethodRtnObj (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsObject (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ private Object callMethodRtnObj (String methodName,
+ Class[] argClasses,
+ Object[] argValues)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ argClasses, argValues)
+ .getReturnValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a 'raw' ProxyReturnValue.
+ private ProxyReturnValue callMethodRtnRaw (String methodName,
+ Class[] argClasses,
+ Object[] argValues)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ argClasses, argValues);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public void clearWarnings ()
+ throws SQLException
+ {
+ callMethod ("clearWarnings");
+ }
+
+
+
+ public void close ()
+ throws SQLException
+ {
+ callMethod ("close");
+ }
+
+
+
+ public int findColumn (String columnName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("findColumn",
+ new Class[] { String.class },
+ new Object[] { columnName })
+ .getReturnValueInt();
+ }
+
+
+
+// JDBC 2.0
+ public int getConcurrency ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getConcurrency");
+ }
+
+
+ public String getCursorName ()
+ throws SQLException
+ {
+ return (String) callMethodRtnObj ("getCursorName");
+ }
+
+
+
+// JDBC 2.0
+ public int getFetchDirection ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getFetchDirection");
+ }
+
+
+
+// JDBC 2.0
+ public int getFetchSize ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getFetchSize");
+ }
+
+
+
+// JDBC 2.0
+ public Statement getStatement ()
+ throws SQLException
+ {
+ if (cachedStatement_ == null)
+ {
+ try {
+ JDStatementProxy newStatement = new JDStatementProxy (jdConnection_);
+ cachedStatement_ = (JDStatementProxy) connection_.callFactoryMethod (
+ pxId_, "getStatement", newStatement);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+ return cachedStatement_;
+ }
+
+
+
+// JDBC 2.0
+ public int getType ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getType");
+ }
+
+
+
+ public SQLWarning getWarnings ()
+ throws SQLException
+ {
+ return (SQLWarning) callMethodRtnObj ("getWarnings");
+ }
+
+
+
+// JDBC 2.0
+ public void setFetchDirection (int fetchDirection)
+ throws SQLException
+ {
+ callMethod ("setFetchDirection",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (fetchDirection) });
+ }
+
+
+
+// JDBC 2.0
+ public void setFetchSize (int fetchSize)
+ throws SQLException
+ {
+ callMethod ("setFetchSize",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (fetchSize) });
+ }
+
+
+ // This method is not required by java.sql.ResultSet,
+ // but it is used by the JDBC testcases, and is implemented
+ // in the public class.
+ public String toString ()
+ {
+ try {
+ return (String) connection_.callMethodReturnsObject (pxId_, "toString");
+ }
+ catch (InvocationTargetException e) {
+ throw ProxyClientConnection.rethrow (e);
+ }
+ }
+
+
+
+/*---------------------------------------------------------*/
+/* */
+/* CURSOR POSITIONING. */
+/* */
+/*---------------------------------------------------------*/
+
+
+
+// JDBC 2.0
+ public boolean absolute (int rowNumber)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("absolute",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (rowNumber) })
+ .getReturnValueBoolean();
+ }
+
+
+
+// JDBC 2.0
+ public void afterLast ()
+ throws SQLException
+ {
+ callMethod ("afterLast");
+ }
+
+
+
+// JDBC 2.0
+ public void beforeFirst ()
+ throws SQLException
+ {
+ callMethod ("beforeFirst");
+ }
+
+
+
+// JDBC 2.0
+ public boolean first ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("first");
+ }
+
+
+
+// JDBC 2.0
+ public int getRow ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getRow");
+ }
+
+
+
+// JDBC 2.0
+ public boolean isAfterLast ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isAfterLast");
+ }
+
+
+
+// JDBC 2.0
+ public boolean isBeforeFirst ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isBeforeFirst");
+ }
+
+
+
+// JDBC 2.0
+ public boolean isFirst ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isFirst");
+ }
+
+
+
+// JDBC 2.0
+ public boolean isLast ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isLast");
+ }
+
+
+
+// JDBC 2.0
+ public boolean last ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("last");
+ }
+
+
+
+// JDBC 2.0
+ public void moveToCurrentRow ()
+ throws SQLException
+ {
+ callMethod ("moveToCurrentRow");
+ }
+
+
+
+// JDBC 2.0
+ public void moveToInsertRow ()
+ throws SQLException
+ {
+ callMethod ("moveToInsertRow");
+ }
+
+
+
+ public boolean next ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("next");
+ }
+
+
+
+// JDBC 2.0
+ public boolean previous ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("previous");
+ }
+
+
+// JDBC 2.0
+ public void refreshRow ()
+ throws SQLException
+ {
+ callMethod ("refreshRow");
+ }
+
+
+
+// JDBC 2.0
+ public boolean relative (int rowNumber)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("relative",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (rowNumber) })
+ .getReturnValueBoolean();
+ }
+
+
+
+/*---------------------------------------------------------*/
+/* */
+/* GET DATA METHODS. */
+/* */
+/*---------------------------------------------------------*/
+
+
+
+// JDBC 2.0
+ public Array getArray (int columnIndex)
+ throws SQLException
+ {
+ return (Array) callMethodRtnObj ("getArray",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+// JDBC 2.0
+ public Array getArray (String columnName)
+ throws SQLException
+ {
+ return getArray (findColumn (columnName));
+ }
+
+
+
+ public InputStream getAsciiStream (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnInpStrm ("getAsciiStream", columnIndex);
+ }
+
+
+
+ public InputStream getAsciiStream (String columnName)
+ throws SQLException
+ {
+ return getAsciiStream (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public BigDecimal getBigDecimal (int columnIndex)
+ throws SQLException
+ {
+ return (BigDecimal) callMethodRtnObj ("getBigDecimal",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+// JDBC 2.0
+ public BigDecimal getBigDecimal (String columnName)
+ throws SQLException
+ {
+ return getBigDecimal (findColumn (columnName));
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use getBigDecimal(int) instead.
+@see #getBigDecimal(int)
+**/
+ public BigDecimal getBigDecimal (int columnIndex, int scale)
+ throws SQLException
+ {
+ return (BigDecimal) callMethodRtnObj ("getBigDecimal",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Integer (scale) });
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use getBigDecimal(String) instead.
+@see #getBigDecimal(String)
+**/
+ public BigDecimal getBigDecimal (String columnName, int scale)
+ throws SQLException
+ {
+ return getBigDecimal (findColumn (columnName), scale);
+ }
+
+
+
+ public InputStream getBinaryStream (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnInpStrm ("getBinaryStream", columnIndex);
+ }
+
+
+
+ public InputStream getBinaryStream (String columnName)
+ throws SQLException
+ {
+ return getBinaryStream (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Blob getBlob (int columnIndex)
+ throws SQLException
+ {
+ try {
+ JDBlobProxy newBlob = new JDBlobProxy ();
+ return (JDBlobProxy) connection_.callFactoryMethod (pxId_,
+ "getBlob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(columnIndex) },
+ newBlob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 2.0
+ public Blob getBlob (String columnName)
+ throws SQLException
+ {
+ return getBlob (findColumn (columnName));
+ }
+
+
+
+ public boolean getBoolean (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getBoolean",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueBoolean();
+ }
+
+
+
+ public boolean getBoolean (String columnName)
+ throws SQLException
+ {
+ return getBoolean (findColumn (columnName));
+ }
+
+
+
+ public byte getByte (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getByte",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueByte();
+ }
+
+
+
+ public byte getByte (String columnName)
+ throws SQLException
+ {
+ return getByte (findColumn (columnName));
+ }
+
+
+
+ public byte[] getBytes (int columnIndex)
+ throws SQLException
+ {
+ return (byte[]) callMethodRtnObj ("getBytes",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+ public byte[] getBytes (String columnName)
+ throws SQLException
+ {
+ return getBytes (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Reader getCharacterStream (int columnIndex)
+ throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getCharacterStream",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 2.0
+ public Reader getCharacterStream (String columnName)
+ throws SQLException
+ {
+ return getCharacterStream (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Clob getClob (int columnIndex)
+ throws SQLException
+ {
+ try {
+ JDClobProxy newClob = new JDClobProxy ();
+ return (JDClobProxy) connection_.callFactoryMethod (pxId_,
+ "getClob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(columnIndex) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 2.0
+ public Clob getClob (String columnName)
+ throws SQLException
+ {
+ return getClob (findColumn (columnName));
+ }
+
+
+
+ public Date getDate (int columnIndex)
+ throws SQLException
+ {
+ return (Date) callMethodRtnObj ("getDate",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+ public Date getDate (String columnName)
+ throws SQLException
+ {
+ return (Date) callMethodRtnObj ("getDate",
+ new Class[] { String.class },
+ new Object[] { columnName });
+ }
+
+
+
+// JDBC 2.0
+ public Date getDate (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Date) callMethodRtnObj ("getDate",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (columnIndex),
+ calendar });
+ }
+
+
+
+// JDBC 2.0
+ public Date getDate (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getDate (findColumn (columnName), calendar);
+ }
+
+
+
+ public double getDouble (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getDouble",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueDouble();
+ }
+
+
+
+ public double getDouble (String columnName)
+ throws SQLException
+ {
+ return getDouble (findColumn (columnName));
+ }
+
+
+
+ public float getFloat (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getFloat",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueFloat();
+ }
+
+
+
+ public float getFloat (String columnName)
+ throws SQLException
+ {
+ return getFloat (findColumn (columnName));
+ }
+
+
+
+ public int getInt (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getInt",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueInt();
+ }
+
+
+
+ public int getInt (String columnName)
+ throws SQLException
+ {
+ return getInt (findColumn (columnName));
+ }
+
+
+
+ public long getLong (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getLong",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueLong();
+ }
+
+
+
+ public long getLong (String columnName)
+ throws SQLException
+ {
+ return getLong (findColumn (columnName));
+ }
+
+
+
+ public ResultSetMetaData getMetaData ()
+ throws SQLException
+ {
+ try {
+ JDResultSetMetaDataProxy newMetaData = new JDResultSetMetaDataProxy (jdConnection_);
+ return (JDResultSetMetaDataProxy) connection_.callFactoryMethod (
+ pxId_, "getMetaData", newMetaData);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public Object getObject (int columnIndex)
+ throws SQLException
+ {
+ String typeName = getMetaData().getColumnTypeName(columnIndex);
+ ProxyFactoryImpl proxyObject = null;
+ try
+ {
+ if (typeName.equalsIgnoreCase("BLOB")) {
+ proxyObject = new JDBlobProxy ();
+ }
+ else if (typeName.equalsIgnoreCase("CLOB")) {
+ proxyObject = new JDClobProxy ();
+ }
+ else
+ return callMethodRtnObj ("getObject",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+
+ return connection_.callFactoryMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) },
+ proxyObject);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public Object getObject (String columnName)
+ throws SQLException
+ {
+ return getObject (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Object getObject (int columnIndex, Map typeMap)
+ throws SQLException
+ {
+ String typeName = getMetaData().getColumnTypeName(columnIndex);
+ ProxyFactoryImpl proxyObject = null;
+ try
+ {
+ if (typeName.equalsIgnoreCase("BLOB")) {
+ proxyObject = new JDBlobProxy ();
+ }
+ else if (typeName.equalsIgnoreCase("CLOB")) {
+ proxyObject = new JDClobProxy ();
+ }
+ else
+ return callMethodRtnObj ("getObject",
+ new Class[] { Integer.TYPE, Map.class },
+ new Object[] { new Integer (columnIndex),
+ typeMap });
+
+ return connection_.callFactoryMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE, Map.class },
+ new Object[] { new Integer (columnIndex),
+ typeMap },
+ proxyObject);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 2.0
+ public Object getObject (String columnName, Map typeMap)
+ throws SQLException
+ {
+ return getObject (findColumn (columnName), typeMap);
+ }
+
+
+
+// JDBC 2.0
+ public Ref getRef (int columnIndex)
+ throws SQLException
+ {
+ return (Ref) callMethodRtnObj ("getRef",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+// JDBC 2.0
+ public Ref getRef (String columnName)
+ throws SQLException
+ {
+ return getRef (findColumn (columnName));
+ }
+
+
+
+ public short getShort (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getShort",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) })
+ .getReturnValueShort();
+ }
+
+
+
+ public short getShort (String columnName)
+ throws SQLException
+ {
+ return getShort (findColumn (columnName));
+ }
+
+
+
+ public String getString (int columnIndex)
+ throws SQLException
+ {
+ return (String) callMethodRtnObj ("getString",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+ public String getString (String columnName)
+ throws SQLException
+ {
+ return getString (findColumn (columnName));
+ }
+
+
+
+ public Time getTime (int columnIndex)
+ throws SQLException
+ {
+ return (Time) callMethodRtnObj ("getTime",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+ public Time getTime (String columnName)
+ throws SQLException
+ {
+ return getTime (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Time getTime (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Time) callMethodRtnObj ("getTime",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (columnIndex),
+ calendar });
+ }
+
+
+
+// JDBC 2.0
+ public Time getTime (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getTime (findColumn (columnName), calendar);
+ }
+
+
+
+ public Timestamp getTimestamp (int columnIndex)
+ throws SQLException
+ {
+ return (Timestamp) callMethodRtnObj ("getTimestamp",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+ public Timestamp getTimestamp (String columnName)
+ throws SQLException
+ {
+ return getTimestamp (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public Timestamp getTimestamp (int columnIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Timestamp) callMethodRtnObj ("getTimestamp",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (columnIndex),
+ calendar });
+ }
+
+
+
+// JDBC 2.0
+ public Timestamp getTimestamp (String columnName, Calendar calendar)
+ throws SQLException
+ {
+ return getTimestamp (findColumn (columnName), calendar);
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use getCharacterStream(int) instead.
+@see #getCharacterStream(int)
+**/
+ public InputStream getUnicodeStream (int columnIndex)
+ throws SQLException
+ {
+ return callMethodRtnInpStrm ("getUnicodeStream", columnIndex);
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use getCharacterStream(String) instead.
+@see #getCharacterStream(String)
+**/
+ public InputStream getUnicodeStream (String columnName)
+ throws SQLException
+ {
+ return getUnicodeStream (findColumn (columnName));
+ }
+
+
+
+// JDBC 3.0
+ public URL getURL (int columnIndex)
+ throws SQLException
+ {
+ return(URL) callMethodRtnObj ("getURL",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer(columnIndex)});
+ }
+
+
+
+// JDBC 3.0
+ public URL getURL (String columnName)
+ throws SQLException
+ {
+ return(URL) callMethodRtnObj ("getURL",
+ new Class[] { String.class},
+ new Object[] { columnName});
+ }
+
+
+
+ public boolean wasNull ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("wasNull");
+ }
+
+
+
+/*---------------------------------------------------------*/
+/* */
+/* UPDATE DATA METHODS. */
+/* */
+/*---------------------------------------------------------*/
+
+
+
+// JDBC 2.0
+ public void cancelRowUpdates ()
+ throws SQLException
+ {
+ callMethod ("cancelRowUpdates");
+ }
+
+
+
+// JDBC 2.0
+ public void deleteRow ()
+ throws SQLException
+ {
+ callMethod ("deleteRow");
+ }
+
+
+
+// JDBC 2.0
+ public void insertRow ()
+ throws SQLException
+ {
+ callMethod ("insertRow");
+ }
+
+
+
+// JDBC 2.0
+ public boolean rowDeleted ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("rowDeleted");
+ }
+
+
+
+// JDBC 2.0
+ public boolean rowInserted ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("rowInserted");
+ }
+
+
+
+// JDBC 2.0
+ public boolean rowUpdated ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("rowUpdated");
+ }
+
+
+
+// JDBC 3.0
+ public void updateArray (int columnIndex, Array columnValue)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateArray",
+ new Class[] { Integer.TYPE, Array.class },
+ new Object[] { new Integer(columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 3.0
+ public void updateArray (String columnName, Array columnValue)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateArray",
+ new Class[] { String.class, Array.class },
+ new Object[] { columnName,
+ columnValue });
+ }
+
+
+
+
+
+// JDBC 2.0
+ public void updateAsciiStream (int columnIndex,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (columnValue == null ||
+ columnValue instanceof Serializable)
+ iStream = columnValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (columnValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ iStream,
+ new Integer (length) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateAsciiStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ updateAsciiStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+// JDBC 2.0
+ public void updateBigDecimal (int columnIndex, BigDecimal columnValue)
+ throws SQLException
+ {
+ callMethod ("updateBigDecimal",
+ new Class[] { Integer.TYPE, BigDecimal.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateBigDecimal (String columnName, BigDecimal columnValue)
+ throws SQLException
+ {
+ updateBigDecimal (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateBinaryStream (int columnIndex,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (columnValue == null ||
+ columnValue instanceof Serializable)
+ iStream = columnValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (columnValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ iStream,
+ new Integer (length) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateBinaryStream (String columnName,
+ InputStream columnValue,
+ int length)
+ throws SQLException
+ {
+ updateBinaryStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+// JDBC 3.0
+ public void updateBlob (int columnIndex, Blob columnValue)
+ throws SQLException
+ {
+ callMethod ("updateBlob",
+ new Class[] { Integer.TYPE, Blob.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 3.0
+ public void updateBlob (String columnName, Blob columnValue)
+ throws SQLException
+ {
+ callMethod ("updateBlob",
+ new Class[] { String.class, Blob.class },
+ new Object[] { columnName,
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateBoolean (int columnIndex, boolean columnValue)
+ throws SQLException
+ {
+ callMethod ("updateBoolean",
+ new Class[] { Integer.TYPE, Boolean.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Boolean (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateBoolean (String columnName, boolean columnValue)
+ throws SQLException
+ {
+ updateBoolean (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateByte (int columnIndex, byte columnValue)
+ throws SQLException
+ {
+ callMethod ("updateByte",
+ new Class[] { Integer.TYPE, Byte.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Byte (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateByte (String columnName, byte columnValue)
+ throws SQLException
+ {
+ updateByte (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateBytes (int columnIndex, byte[] columnValue)
+ throws SQLException
+ {
+ callMethod ("updateBytes",
+ new Class[] { Integer.TYPE, byte[].class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateBytes (String columnName, byte[] columnValue)
+ throws SQLException
+ {
+ updateBytes (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateCharacterStream (int columnIndex,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (columnValue == null)
+ reader = null;
+ else
+ reader = new SerializableReader (columnValue, Math.max(0,length));
+ callMethod ("updateCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class, Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ reader, new Integer (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+
+// JDBC 2.0
+ public void updateCharacterStream (String columnName,
+ Reader columnValue,
+ int length)
+ throws SQLException
+ {
+ updateCharacterStream (findColumn (columnName), columnValue, length);
+ }
+
+
+
+// JDBC 3.0
+ public void updateClob (int columnIndex, Clob columnValue)
+ throws SQLException
+ {
+ callMethod ("updateClob",
+ new Class[] { String.class, Clob.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 3.0
+ public void updateClob (String columnName, Clob columnValue)
+ throws SQLException
+ {
+ callMethod ("updateClob",
+ new Class[] { String.class, Clob.class },
+ new Object[] { columnName,
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateDate (int columnIndex, Date columnValue)
+ throws SQLException
+ {
+ callMethod ("updateDate",
+ new Class[] { Integer.TYPE, Date.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateDate (String columnName, Date columnValue)
+ throws SQLException
+ {
+ updateDate (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateDouble (int columnIndex, double columnValue)
+ throws SQLException
+ {
+ callMethod ("updateDouble",
+ new Class[] { Integer.TYPE, Double.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Double (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateDouble (String columnName, double columnValue)
+ throws SQLException
+ {
+ updateDouble (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateFloat (int columnIndex, float columnValue)
+ throws SQLException
+ {
+ callMethod ("updateFloat",
+ new Class[] { Integer.TYPE, Float.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Float (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateFloat (String columnName, float columnValue)
+ throws SQLException
+ {
+ updateFloat (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateInt (int columnIndex, int columnValue)
+ throws SQLException
+ {
+ callMethod ("updateInt",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Integer (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateInt (String columnName, int columnValue)
+ throws SQLException
+ {
+ updateInt (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateLong (int columnIndex, long columnValue)
+ throws SQLException
+ {
+ callMethod ("updateLong",
+ new Class[] { Integer.TYPE, Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Long (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateLong (String columnName, long columnValue)
+ throws SQLException
+ {
+ updateLong (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateNull (int columnIndex)
+ throws SQLException
+ {
+ callMethod ("updateNull",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateNull (String columnName)
+ throws SQLException
+ {
+ updateNull (findColumn (columnName));
+ }
+
+
+
+// JDBC 2.0
+ public void updateObject (int columnIndex, Object columnValue)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable)) {
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateObject",
+ new Class[] { Integer.TYPE, Object.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateObject (String columnName, Object columnValue)
+ throws SQLException
+ {
+ updateObject (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateObject (int columnIndex,
+ Object columnValue,
+ int scale)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable)) {
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateObject",
+ new Class[] { Integer.TYPE, Object.class, Integer.TYPE },
+ new Object[] { new Integer (columnIndex),
+ columnValue,
+ new Integer (scale) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateObject (String columnName,
+ Object columnValue,
+ int scale)
+ throws SQLException
+ {
+ updateObject (findColumn (columnName), columnValue, scale);
+ }
+
+
+
+// JDBC 3.0
+ public void updateRef (int columnIndex, Ref columnValue)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateRef",
+ new Class[] { Integer.TYPE, Ref.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 3.0
+ public void updateRef (String columnName, Ref columnValue)
+ throws SQLException
+ {
+ if (columnValue != null &&
+ !(columnValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("updateRef",
+ new Class[] { String.class, Ref.class },
+ new Object[] { columnName,
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateRow ()
+ throws SQLException
+ {
+ callMethod ("updateRow");
+ }
+
+
+
+// JDBC 2.0
+ public void updateShort (int columnIndex, short columnValue)
+ throws SQLException
+ {
+ callMethod ("updateShort",
+ new Class[] { Integer.TYPE, Short.TYPE },
+ new Object[] { new Integer (columnIndex),
+ new Short (columnValue) });
+ }
+
+
+
+// JDBC 2.0
+ public void updateShort (String columnName, short columnValue)
+ throws SQLException
+ {
+ updateShort (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateString (int columnIndex, String columnValue)
+ throws SQLException
+ {
+ callMethod ("updateString",
+ new Class[] { Integer.TYPE, String.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateString (String columnName, String columnValue)
+ throws SQLException
+ {
+ updateString (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateTime (int columnIndex, Time columnValue)
+ throws SQLException
+ {
+ callMethod ("updateTime",
+ new Class[] { Integer.TYPE, Time.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateTime (String columnName, Time columnValue)
+ throws SQLException
+ {
+ updateTime (findColumn (columnName), columnValue);
+ }
+
+
+
+// JDBC 2.0
+ public void updateTimestamp (int columnIndex, Timestamp columnValue)
+ throws SQLException
+ {
+ callMethod ("updateTimestamp",
+ new Class[] { Integer.TYPE, Timestamp.class },
+ new Object[] { new Integer (columnIndex),
+ columnValue });
+ }
+
+
+
+// JDBC 2.0
+ public void updateTimestamp (String columnName, Timestamp columnValue)
+ throws SQLException
+ {
+ updateTimestamp (findColumn (columnName), columnValue);
+ }
+
+
+ //@PDA jdbc40
+ public int getHoldability() throws SQLException
+ {
+ return callMethodRtnInt ("getHoldability");
+ }
+
+
+ //@pda jdbc40
+ public Reader getNCharacterStream(int columnIndex) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getNCharacterStream",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Retrieves the value of the designated column in the current row
+ * of this The implementation's constructor should not necessarily
+initialize the data. That is done via the set() methods.
+**/
+interface SQLData
+extends Cloneable
+{
+ //NATIVE_ARRAY is defined here for the array type received from zda. But zda does not have a visible array type.
+ //zda uses a bit that flags if the stream is an array.
+ //So we just define it here as 10000. This number is not important; it just needs to be different from other native type numbers.
+ //This is used in SQLDataFactory and other array related classes.
+ public static final short NATIVE_ARRAY = 10000; //@array
+
+ public static final int UNDEFINED = 0;
+ public static final int BIGINT = 1;
+ public static final int BINARY = 2;
+ public static final int BLOB = 3;
+ public static final int BLOB_LOCATOR = 4;
+ public static final int CHAR = 5;
+ public static final int CHAR_FOR_BIT_DATA = 6;
+ public static final int CLOB = 7;
+ public static final int CLOB_LOCATOR = 8;
+ public static final int DATALINK = 9;
+ public static final int DATE = 10;
+ public static final int DBCLOB = 11;
+ public static final int DBCLOB_LOCATOR = 12;
+ public static final int DECIMAL = 13;
+ public static final int DECIMAL_USING_DOUBLE = 14;
+ public static final int DOUBLE = 15;
+ public static final int FLOAT = 16;
+ public static final int GRAPHIC = 17;
+ public static final int INTEGER = 18;
+ public static final int LONG_VARCHAR = 19;
+ public static final int LONG_VARCHAR_FOR_BIT_DATA = 20;
+ public static final int LONG_VARGRAPHIC = 21;
+ public static final int NUMERIC = 22;
+ public static final int NUMERIC_USING_DOUBLE = 23;
+ public static final int REAL = 24;
+ public static final int ROWID = 25;
+ public static final int SMALLINT = 26;
+ public static final int TIME = 27;
+ public static final int TIMESTAMP = 28;
+ public static final int VARBINARY = 29;
+ public static final int VARCHAR = 30;
+ public static final int VARCHAR_FOR_BIT_DATA = 31;
+ public static final int VARGRAPHIC = 32;
+ public static final int NCLOB = 33; //@PDA jdbc40 (jdbc40 just added here for info)
+ public static final int NCLOB_LOCATOR = 34; //@PDA jdbc40
+ public static final int NCHAR = 35; //@PDA jdbc40
+ public static final int NVARCHAR = 36; //@PDA jdbc40
+ public static final int LONG_NVARCHAR = 37; //@pda jdbc40
+ public static final int DECFLOAT = 38; //@DFA
+ public static final int ARRAY = 39; //@array
+ public static final int XML_LOCATOR = 40; //@xml3
+
+ /**
+ Returns a clone of the SQLData object. Use this sparingly
+ so that we minimize the number of copies.
+ @return The clone.
+ **/
+ public abstract Object clone();
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ /**
+ Loads the contents of the data from raw bytes, as returned
+ in a reply from the system.
+ @param rawBytes raw bytes from the system.
+ @param offset offset.
+ @param converter the converter.
+ @exception SQLException If the raw bytes are not in
+ the expected format.
+ **/
+ public abstract void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable converter)
+ throws SQLException;
+
+ /**
+ Converts the contents of the data in raw bytes, as needed
+ in a request to the system.
+ @param rawBytes the raw bytes for the system.
+ @param offset the offset into the byte array.
+ @param ccsidConverter the converter.
+ **/
+ public abstract void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException;
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ // The set methods initialize the data in a uniform way //
+ // across all types. If a specific initialization is //
+ // needed based on a Java type, then add other flavors //
+ // of set() methods. //
+ // //
+ //---------------------------------------------------------//
+
+ /**
+ Sets the contents of the data based on a Java object.
+ This performs all conversions described in Table 6
+ of the JDBC specification.
+ @param object a Java object.
+ @param calendar The calendar.
+ @param scale The scale.
+ @exception SQLException If the Java object is not an
+ appropriate type.
+ **/
+ public abstract void set(Object object, Calendar calendar, int scale)
+ throws SQLException;
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ // These methods describe information about the actual //
+ // type of data. //
+ // //
+ /*---------------------------------------------------------*/
+
+ /**
+ Returns the SQL type constant for the implementing class.
+ @return the SQL type constant.
+ **/
+ public abstract int getSQLType();
+
+ /**
+ Returns the parameters used in creating the
+ type.
+ @return the parameters, separated by commas,
+ or null if none.
+ **/
+ public abstract String getCreateParameters();
+
+ /**
+ Returns the display size. This is defined in Appendix
+ D of the ODBC 2.0 Programmer's Reference.
+ @return the display size (in characters).
+ @exception SQLException If the index is invalid
+ or an error occurs.
+ **/
+ public abstract int getDisplaySize();
+
+ //@F1A JDBC 3.0
+ /**
+ Returns the Java class name for ParameterMetaData.getParameterClassName().
+ @return the Java class name.
+ **/
+ public abstract String getJavaClassName();
+
+ /**
+ Returns the prefix used to quote a literal.
+ @return the prefix, or null if none.
+ **/
+ public abstract String getLiteralPrefix();
+
+ /**
+ Returns the suffix used to quote a literal.
+ @return the suffix, or null if none.
+ **/
+ public abstract String getLiteralSuffix();
+
+ /**
+ Returns the localized version of the name of the
+ data type.
+ @return the name, or null.
+ **/
+ public abstract String getLocalName();
+
+ /**
+ Returns the maximum precision of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the maximum precision.
+ **/
+ public abstract int getMaximumPrecision();
+
+ /**
+ Returns the maximum scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the maximum scale.
+ **/
+ public abstract int getMaximumScale();
+
+ /**
+ Returns the minimum scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the minimum scale.
+ **/
+ public abstract int getMinimumScale();
+
+ /**
+ Returns the native IBM i identifier for the type.
+ @return the native type.
+ **/
+ public abstract int getNativeType();
+
+ /**
+ Returns the precision of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the precision.
+ **/
+ public abstract int getPrecision();
+
+ /**
+ Returns the radix for the type.
+ @return the radix.
+ **/
+ public abstract int getRadix();
+
+ /**
+ Returns the scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the scale.
+ **/
+ public abstract int getScale();
+
+ /**
+ Returns the type constant associated with the type.
+ @return SQL type code defined in java.sql.Types.
+ **/
+ public abstract int getType();
+
+ /**
+ Returns the name of the data type.
+ @return the name.
+ **/
+ public abstract String getTypeName();
+
+ /**
+ Indicates whether the type is signed.
+ @return true or false
+ **/
+ public abstract boolean isSigned();
+
+ /**
+ Indicates whether the type is text. This also
+ indicates that the associated data needs to be
+ converted.
+ @return true or false
+ **/
+ public abstract boolean isText();
+
+ /**
+ Returns the actual size of this piece of data in bytes.
+ @return the actual size of this piece of data in bytes.
+ **/
+ public abstract int getActualSize();
+
+ /**
+ Returns the number of bytes truncated by the last conversion
+ of this piece of data.
+ @return the number of bytes truncated by the last conversion
+ **/
+ public abstract int getTruncated();
+
+ /**
+ * Returns true if the last conversion of this piece of
+ * data was out of bounds of the range of the requested
+ * datatype. This will only happen when requesting
+ * conversion to a numeric type.
+ */
+ public abstract boolean getOutOfBounds();
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ // These methods convert the data to a specific Java //
+ // type. These conversions should be provided per //
+ // section 7, table 1 ("Use of ResultSet.getXxx methods //
+ // to retrieve common SQL data types") of the JDBC 1.10 //
+ // specification. If a conversion is not required or is //
+ // not possible given the data, then the method should //
+ // throw an exception. //
+ // //
+ /*---------------------------------------------------------*/
+
+ /**
+ Converts the data to a stream of ASCII characters.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract InputStream getAsciiStream()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java BigDecimal object.
+ @param scale scale, or -1 to use full scale.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract BigDecimal getBigDecimal(int scale)
+ throws SQLException;
+
+ /**
+ Converts the data to a stream of uninterpreted bytes.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract InputStream getBinaryStream()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Blob object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Blob getBlob()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java boolean.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract boolean getBoolean()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java byte.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract byte getByte()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java byte array containing
+ uninterpreted bytes.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract byte[] getBytes()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.io.Reader object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Reader getCharacterStream()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Clob object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Clob getClob()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Date object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Date getDate(Calendar calendar)
+ throws SQLException;
+
+ /**
+ Converts the data to a Java double.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract double getDouble()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java float.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract float getFloat()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java int.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract int getInt()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java long.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract long getLong()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java object. The actual type
+ of the Java object is dictated per section 8,
+ table 2 ("Standard mapping from SQL types to Java types")
+ of the JDBC 1.10 specification
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Object getObject()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java short.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract short getShort()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java String object. This
+ conversion must be provided by the implementation.
+ @return the result of the conversion.
+ **/
+ public abstract String getString()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Time object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Time getTime(Calendar calendar)
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Timestamp object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Timestamp getTimestamp(Calendar calendar)
+ throws SQLException;
+
+ /**
+ Converts the data to a stream of Unicdoe characters.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract InputStream getUnicodeStream()
+ throws SQLException;
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.io.Reader object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Reader getNCharacterStream()
+ throws SQLException;
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.NClob object
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+ public abstract NClob getNClob()
+ throws SQLException;
+/* endif */
+ //@PDA jdbc40
+ /**
+ Converts the data to String object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract String getNString()
+ throws SQLException;
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.SQLXML object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+ public abstract SQLXML getSQLXML()
+ throws SQLException;
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.RowId object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+
+ public abstract RowId getRowId()
+ throws SQLException;
+/* endif */
+
+ //@array
+ /**
+ Converts (returns) the data to a java.sql.Array object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Array getArray()
+ throws SQLException;
+
+ public abstract void updateSettings(SQLConversionSettings settings);
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDataBase.java b/jdbc40/com/ibm/as400/access/SQLDataBase.java
new file mode 100644
index 000000000..2b61ddb74
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDataBase.java
@@ -0,0 +1,803 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLData.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.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+/**
+The SQLData interface represents native SQL data. A specific
+implementation of this interface will implement a specific
+type of SQL data.
+
+ This base class contains conversion methods usable by the sub classes.
+**/
+public abstract class SQLDataBase implements SQLData
+{
+
+ static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others.";
+
+ protected int truncated_;
+ protected boolean outOfBounds_;
+ protected SQLConversionSettings settings_;
+
+ public SQLDataBase(SQLConversionSettings settings) {
+ this.settings_= settings;
+ truncated_ = 0; outOfBounds_ = false;
+
+ }
+ /**
+ Returns a clone of the SQLData object. Use this sparingly
+ so that we minimize the number of copies.
+ @return The clone.
+ **/
+ public abstract Object clone();
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ /**
+ Loads the contents of the data from raw bytes, as returned
+ in a reply from the system.
+ @param rawBytes raw bytes from the system.
+ @param offset offset.
+ @param converter the converter.
+ @exception SQLException If the raw bytes are not in
+ the expected format.
+ **/
+ public abstract void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable converter)
+ throws SQLException;
+
+ /**
+ Converts the contents of the data in raw bytes, as needed
+ in a request to the system.
+ @param rawBytes the raw bytes for the system.
+ @param offset the offset into the byte array.
+ @param ccsidConverter the converter.
+ **/
+ public abstract void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException;
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ // The set methods initialize the data in a uniform way //
+ // across all types. If a specific initialization is //
+ // needed based on a Java type, then add other flavors //
+ // of set() methods. //
+ // //
+ //---------------------------------------------------------//
+
+ /**
+ Sets the contents of the data based on a Java object.
+ This performs all conversions described in Table 6
+ of the JDBC specification.
+ @param object a Java object.
+ @param calendar The calendar.
+ @param scale The scale.
+ @exception SQLException If the Java object is not an
+ appropriate type.
+ **/
+ public abstract void set(Object object, Calendar calendar, int scale)
+ throws SQLException;
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ // These methods describe information about the actual //
+ // type of data. //
+ // //
+ /*---------------------------------------------------------*/
+
+ /**
+ Returns the SQL type constant for the implementing class.
+ @return the SQL type constant.
+ **/
+ public abstract int getSQLType();
+
+ /**
+ Returns the parameters used in creating the
+ type.
+ @return the parameters, separated by commas,
+ or null if none.
+ **/
+ public abstract String getCreateParameters();
+
+ /**
+ Returns the display size. This is defined in Appendix
+ D of the ODBC 2.0 Programmer's Reference.
+ @return the display size (in characters).
+ @exception SQLException If the index is invalid
+ or an error occurs.
+ **/
+ public abstract int getDisplaySize();
+
+ //@F1A JDBC 3.0
+ /**
+ Returns the Java class name for ParameterMetaData.getParameterClassName().
+ @return the Java class name.
+ **/
+ public abstract String getJavaClassName();
+
+ /**
+ Returns the prefix used to quote a literal.
+ @return the prefix, or null if none.
+ **/
+ public abstract String getLiteralPrefix();
+
+ /**
+ Returns the suffix used to quote a literal.
+ @return the suffix, or null if none.
+ **/
+ public abstract String getLiteralSuffix();
+
+ /**
+ Returns the localized version of the name of the
+ data type.
+ @return the name, or null.
+ **/
+ public abstract String getLocalName();
+
+ /**
+ Returns the maximum precision of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the maximum precision.
+ **/
+ public abstract int getMaximumPrecision();
+
+ /**
+ Returns the maximum scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the maximum scale.
+ **/
+ public abstract int getMaximumScale();
+
+ /**
+ Returns the minimum scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the minimum scale.
+ **/
+ public abstract int getMinimumScale();
+
+ /**
+ Returns the native IBM i identifier for the type.
+ @return the native type.
+ **/
+ public abstract int getNativeType();
+
+ /**
+ Returns the precision of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the precision.
+ **/
+ public abstract int getPrecision();
+
+ /**
+ Returns the radix for the type.
+ @return the radix.
+ **/
+ public abstract int getRadix();
+
+ /**
+ Returns the scale of the type. This is
+ defined in Appendix D of the ODBC 2.0 Programmer's
+ Reference.
+ @return the scale.
+ **/
+ public abstract int getScale();
+
+ /**
+ Returns the type constant associated with the type.
+ @return SQL type code defined in java.sql.Types.
+ **/
+ public abstract int getType();
+
+ /**
+ Returns the name of the data type.
+ @return the name.
+ **/
+ public abstract String getTypeName();
+
+ /**
+ Indicates whether the type is signed.
+ @return true or false
+ **/
+ public abstract boolean isSigned();
+
+ /**
+ Indicates whether the type is text. This also
+ indicates that the associated data needs to be
+ converted.
+ @return true or false
+ **/
+ public abstract boolean isText();
+
+ /**
+ Returns the actual size of this piece of data in bytes.
+ @return the actual size of this piece of data in bytes.
+ **/
+ public abstract int getActualSize();
+
+ /**
+ Returns the number of bytes truncated by the last conversion
+ of this piece of data.
+ @return the number of bytes truncated by the last conversion
+ **/
+ public abstract int getTruncated();
+
+ /**
+ * Returns true if the last conversion of this piece of
+ * data was out of bounds of the range of the requested
+ * datatype. This will only happen when requesting
+ * conversion to a numeric type.
+ */
+ public abstract boolean getOutOfBounds();
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ // These methods convert the data to a specific Java //
+ // type. These conversions should be provided per //
+ // section 7, table 1 ("Use of ResultSet.getXxx methods //
+ // to retrieve common SQL data types") of the JDBC 1.10 //
+ // specification. If a conversion is not required or is //
+ // not possible given the data, then the method should //
+ // throw an exception. //
+ // //
+ /*---------------------------------------------------------*/
+
+ /**
+ Converts the data to a stream of ASCII characters.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public InputStream getAsciiStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return new ByteArrayInputStream(ConvTable.getTable(819, null).stringToByteArray(getString()));
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+ /**
+ Converts the data to a Java BigDecimal object.
+ @param scale scale, or -1 to use full scale.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ try
+ {
+ BigDecimal bigDecimal = new BigDecimal(SQLDataFactory.convertScientificNotation(getString().trim(), settings_)); // @F5C
+ if(scale >= 0)
+ {
+ if(scale >= bigDecimal.scale())
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return bigDecimal.setScale(scale);
+ }
+ else
+ {
+ truncated_ = bigDecimal.scale() - scale; outOfBounds_ = false;
+ return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return bigDecimal;
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return null;
+ }
+ }
+
+
+ /**
+ Converts the data to a stream of uninterpreted bytes.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract InputStream getBinaryStream()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Blob object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Blob getBlob()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java boolean.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ // If value equals "true", "false", "1", or "0", then return the
+ // corresponding boolean, otherwise an empty string is
+ // false, a non-empty string is true.
+ String trimmedValue = getString().trim();
+ return((trimmedValue.length() > 0)
+ && (! trimmedValue.equalsIgnoreCase("false"))
+ && (! trimmedValue.equals("0")));
+ }
+
+ /**
+ Converts the data to a Java byte.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ //return(new Double(value_.trim())).byteValue(); //@trunc
+ Double doubleValue = new Double (getString().trim ()); //@trunc
+ double d = doubleValue.doubleValue(); //@trunc
+ if(d > Byte.MAX_VALUE || d < Byte.MIN_VALUE) { //@trunc
+ truncated_ = 1; //@trunc
+ outOfBounds_ = true;
+ }
+
+ return doubleValue.byteValue (); //@trunc
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+
+ /**
+ Converts the data to a Java byte array containing
+ uninterpreted bytes.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract byte[] getBytes()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.io.Reader object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public Reader getCharacterStream()
+ throws SQLException
+ {
+ return new java.io.StringReader(getString());
+ }
+
+ /**
+ Converts the data to a java.sql.Clob object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public Clob getClob()
+ throws SQLException
+ {
+ String string = getString();
+ // Use the default maximum length for the obtained clob
+ return new AS400JDBCClob(string);
+ }
+
+ /**
+ Converts the data to a java.sql.Date object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(calendar == null) //@dat1
+ {
+ //getter methods do not enforce strict conversion
+ calendar = AS400Calendar.getGregorianInstance(); //@dat1
+ }
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+ return SQLDate.stringToDate(getString(), settings_, calendar);
+ }
+
+
+ /**
+ Converts the data to a Java double.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return(new Double(getString().trim())).doubleValue();
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+
+ /**
+ Converts the data to a Java float.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return(new Double(getString().trim())).floatValue();
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+ /**
+ Converts the data to a Java int.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ //return(new Double(getString().trim())).intValue(); //@trunc
+ Double doubleValue = new Double (getString().trim ()); //@trunc
+ double d = doubleValue.doubleValue(); //@trunc
+
+ if( d > Integer.MAX_VALUE || d < Integer.MIN_VALUE) { //@trunc
+ truncated_ = 1; //@trunc
+ outOfBounds_ = true;
+ }
+
+ return doubleValue.intValue (); //@trunc
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+ /**
+ Converts the data to a Java long.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ //return(new Double(getString().trim())).longValue(); //@trunc
+ Double doubleValue = new Double (getString().trim ()); //@trunc
+ double d = doubleValue.doubleValue(); //@trunc
+
+ if( d > Long.MAX_VALUE || d < Long.MIN_VALUE) { //@trunc
+ truncated_ = 1; //@trunc
+ outOfBounds_ = true;
+ }
+
+ return doubleValue.longValue (); //@trunc
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+
+
+
+
+ /**
+ Converts the data to a Java object. The actual type
+ of the Java object is dictated per section 8,
+ table 2 ("Standard mapping from SQL types to Java types")
+ of the JDBC 1.10 specification
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public abstract Object getObject()
+ throws SQLException;
+
+ /**
+ Converts the data to a Java short.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ //return(new Double(getString().trim())).shortValue(); //@trunc
+ Double doubleValue = new Double (getString().trim ()); //@trunc
+ double d = doubleValue.doubleValue(); //@trunc
+
+ if( d > Short.MAX_VALUE || d < Short.MIN_VALUE) { //@trunc
+ truncated_ = 1; //@trunc
+ outOfBounds_ = true;
+ }
+
+ return doubleValue.shortValue (); //@trunc
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return -1;
+ }
+ }
+
+
+ /**
+ Converts the data to a Java String object. This
+ conversion must be provided by the implementation.
+ @return the result of the conversion.
+ **/
+ public abstract String getString()
+ throws SQLException;
+
+ /**
+ Converts the data to a java.sql.Time object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(calendar == null) //@dat1
+ {
+ //getter methods do not enforce strict conversion
+ calendar = AS400Calendar.getGregorianInstance(); //@dat1
+ }
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+ return SQLTime.stringToTime(getString(), settings_, calendar);
+ }
+
+
+ /**
+ Converts the data to a java.sql.Timestamp object.
+ @param calendar The calendar.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(calendar == null) //@dat1
+ {
+ //getter methods do not enforce strict conversion
+ calendar = AS400Calendar.getGregorianInstance(); //@dat1
+ }
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+ return SQLTimestamp.stringToTimestamp(getString(), calendar);
+ }
+
+ /**
+ Converts the data to a stream of Unicdoe characters.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public InputStream getUnicodeStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return new ReaderInputStream(new StringReader(getString()), 13488);
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.io.Reader object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public Reader getNCharacterStream() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ // This is written in terms of getNString(), since it will
+ // handle truncating to the max field size if needed.
+ return new StringReader(getNString());
+ }
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.NClob object
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+ public NClob getNClob() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ // This is written in terms of getNString(), since it will
+ // handle truncating to the max field size if needed.
+ String string = getNString();
+ return new AS400JDBCNClob(string, string.length());
+ }
+/* endif */
+ //@PDA jdbc40
+ /**
+ Converts the data to String object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+ public String getNString() throws SQLException {
+ return getString();
+ }
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.SQLXML object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+ public abstract SQLXML getSQLXML()
+ throws SQLException;
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ Converts the data to a java.sql.RowId object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+/* ifdef JDBC40 */
+
+ public abstract RowId getRowId()
+ throws SQLException;
+/* endif */
+
+ //@array
+ /**
+ Converts (returns) the data to a java.sql.Array object.
+ @return the result of the conversion.
+ @exception SQLException If the conversion is not
+ required or not possible.
+ **/
+
+ public Array getArray() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public void updateSettings(SQLConversionSettings settings) {
+ settings_ = settings;
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDatalink.java b/jdbc40/com/ibm/as400/access/SQLDatalink.java
new file mode 100644
index 000000000..fc381793f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDatalink.java
@@ -0,0 +1,403 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLDatalink.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.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.net.MalformedURLException;
+
+final class SQLDatalink
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+ // Private data.
+ private int length_;
+ private int maxLength_;
+ private String value_;
+
+ SQLDatalink(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings);
+ length_ = 0;
+ maxLength_ = maxLength;
+ value_ = ""; // @A1C
+ }
+
+ public Object clone()
+ {
+ return new SQLDatalink(maxLength_, settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ length_ = BinaryConverter.byteArrayToUnsignedShort(rawBytes, offset);
+ value_ = ccsidConverter.byteArrayToString(rawBytes, offset+2, length_);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ BinaryConverter.unsignedShortToByteArray(length_, rawBytes, offset);
+ try
+ {
+ ccsidConverter.stringToByteArray(value_, rawBytes, offset + 2, length_);
+ }
+ catch(Exception e)
+ {
+ JDError.throwSQLException(JDError.EXC_INTERNAL, e); // @C2A
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ if(object instanceof String) {
+ value_ = (String)object;
+ } else if (object instanceof java.net.URL) { /*@FCA*/
+ value_ = ((java.net.URL)object).toExternalForm();
+ } else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ length_ = value_.length();
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.DATALINK;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ return maxLength_;
+ }
+
+ //@D1A JDBC 3.0
+ //@d2a - method rewritten for URLs
+ //@j4c - rewritten now that JDUtilites knows the JDBC level
+ public String getJavaClassName()
+ {
+ if(JDUtilities.JDBCLevel_ >= 30)
+ return "java.net.URL";
+ else
+ return "java.lang.Datalink";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return "\'";
+ }
+
+ public String getLiteralSuffix()
+ {
+ return "\'";
+ }
+
+ public String getLocalName()
+ {
+ return "DATALINK";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 32717;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 396;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ if(JDUtilities.JDBCLevel_ >= 30) //@J5A
+ return 70; //java.sql.Types.DATALINK without requiring 1.4 //@J5A
+ else //@J5A
+ return java.sql.Types.VARCHAR;
+ }
+
+ public String getTypeName()
+ {
+ return "DATALINK";
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return value_.length();
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+ public InputStream getAsciiStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return new ByteArrayInputStream(ConvTable.getTable(819, null).stringToByteArray(value_));
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return false;
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ // @d2a entire method reworked. Used to simply return value_.
+ // @j4c - rewritten now that JDUtilites knows the JDBC level
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // if JDBC 3.0 or later return a URL instead of a string.
+ // If we are not able to turn the string into a URL then return
+ // the string (that is why there is no "else". That shouldn't
+ // happen because the database makes sure the cell contains
+ // a valid URL for this data type.
+ if(JDUtilities.JDBCLevel_ >= 30)
+ {
+ try
+ {
+ return new java.net.URL(value_);
+ }
+ catch(MalformedURLException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return null;
+ }
+ }
+ else
+ {
+ return value_;
+ }
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ return value_;
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ return value_;
+ }
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ // @array
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLDate.java b/jdbc40/com/ibm/as400/access/SQLDate.java
new file mode 100644
index 000000000..e411403f5
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDate.java
@@ -0,0 +1,739 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLDate.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.CharConversionException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLDate
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2002 International Business Machines Corporation and others.";
+
+ static boolean jdk14 = false;
+ static {
+ jdk14 = JVMInfo.isJDK14();
+ }
+
+ // Private data.
+ private int dateFormat_; // @550A
+ private int year_;
+ private int month_;
+ private int day_;
+
+ SQLDate(SQLConversionSettings settings, int dateFormat)
+ {
+ super(settings);
+ year_ = 0;
+ month_ = 0;
+ day_ = 0;
+ dateFormat_ = dateFormat; // @550A
+ }
+
+ public Object clone()
+ {
+ return new SQLDate(settings_, dateFormat_); // @550C
+ }
+
+ public static Date stringToDate(String s,
+ SQLConversionSettings settings,
+ Calendar calendar)
+ throws SQLException
+ {
+ // If the string is empty or set to zeros,
+ // then it is likely a NULL, so just set this
+ // to a default date.
+ String sTrim = s.trim();
+ int sTrimLength = sTrim.length(); // @F2A
+ try
+ {
+ if((sTrimLength == 0) || (Integer.parseInt(sTrim) == 0)) // @F2C
+ return new Date(0);
+ }
+ catch(NumberFormatException e)
+ {
+ // Ignore. This just means the value is not NULL.
+ }
+
+ if(calendar == null) {
+ calendar = AS400Calendar.getGregorianInstance(); //@P0A
+ calendar.setLenient(false); //@dat1
+ } else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+
+ try
+ {
+ // Parse the string according to the format and separator.
+ switch(settings.getDateFormat())
+ {
+ case SQLConversionSettings.DATE_FORMAT_USA:
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(6, 10)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(0, 2)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(3, 5)));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_EUR:
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(6, 10)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(3, 5)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(0, 2)));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_JULIAN:
+ if(sTrimLength <= 6)
+ { // YY/DDD // @F2C
+ calendar.set(Calendar.DAY_OF_YEAR, Integer.parseInt(s.substring(3, 6)));
+ calendar.set(Calendar.YEAR, twoDigitYearToFour(Integer.parseInt(s.substring(0, 2))));
+ }
+ else
+ { // Assume they've specified a 4-digit year: YYYY/DDD // @F2A
+ calendar.set(Calendar.DAY_OF_YEAR, Integer.parseInt(s.substring(5, 8)));
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(0, 4)));
+ }
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_MDY:
+ if(sTrimLength <= 8)
+ { // MM/DD/YY // @F2C
+ calendar.set(Calendar.YEAR, twoDigitYearToFour(Integer.parseInt(s.substring(6, 8))));
+ }
+ else
+ { // Assume they've specified a 4-digit year: MM/DD/YYYY // @F2A
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(6, 10)));
+ }
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(0, 2)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(3, 5)));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_DMY:
+ if(sTrimLength <= 8)
+ { // DD/MM/YY // @F2C
+ calendar.set(Calendar.YEAR, twoDigitYearToFour(Integer.parseInt(s.substring(6, 8))));
+ }
+ else
+ { // Assume they've specified a 4-digit year: DD/MM/YYYY // @F2A
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(6, 10)));
+ }
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(3, 5)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(0, 2)));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_YMD:
+ if(sTrimLength <= 8)
+ { // YY/MM/DD // @F2C
+ calendar.set(Calendar.YEAR, twoDigitYearToFour(Integer.parseInt(s.substring(0, 2))));
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(3, 5)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(6, 8)));
+ }
+ else
+ { // Assume they've specified a 4-digit year: YYYY/MM/DD // @F2A
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(0, 4)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(5, 7)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(8, 10)));
+ }
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_JIS:
+ case SQLConversionSettings.DATE_FORMAT_ISO:
+ calendar.set(Calendar.YEAR, Integer.parseInt(s.substring(0, 4)));
+ calendar.set(Calendar.MONTH, Integer.parseInt(s.substring(5, 7)) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.substring(8, 10)));
+ break;
+ }
+
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+ catch(NumberFormatException e)
+ {
+ if (JDTrace.isTraceOn()) JDTrace.logException((Object)null, "Error parsing date "+s, e);
+ JDError.throwSQLException(JDError.EXC_DATA_TYPE_MISMATCH, s);
+ }
+ catch(StringIndexOutOfBoundsException e)
+ {
+ if (JDTrace.isTraceOn()) JDTrace.logException((Object)null, "Error parsing date "+s, e);
+ JDError.throwSQLException(JDError.EXC_DATA_TYPE_MISMATCH, s);
+ }
+
+ try //@dat1
+ {
+ long millis;
+ if (jdk14) { millis =calendar.getTimeInMillis(); } else { millis = calendar.getTime().getTime(); }
+ return new Date(millis);
+ }catch(Exception e){
+ if (JDTrace.isTraceOn()) JDTrace.logException((Object)null, "Error parsing date "+s, e); //@dat1
+ JDError.throwSQLException(JDError.EXC_DATA_TYPE_MISMATCH, s); //@dat1
+ return null; //@dat1
+ }
+ }
+
+ public static String dateToString(java.util.Date d, // @F5C
+ SQLConversionSettings dataFormat,
+ Calendar calendar)
+ {
+ StringBuffer buffer = new StringBuffer();
+ String separator = dataFormat.getDateSeparator();
+ if(calendar == null) { calendar = AS400Calendar.getGregorianInstance(); //@P0A
+
+ }
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+
+ calendar.setTime(d);
+
+ // @F3D Note: No matter what format is being used, ensure that exactly 10 characters are in the buffer.
+
+ switch(dataFormat.getDateFormat())
+ {
+
+ case SQLConversionSettings.DATE_FORMAT_USA: // mm/dd/yyyy
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append('/');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ buffer.append('/');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 4));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_EUR: // dd.mm.yyyy
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ buffer.append('.');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append('.');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 4));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_JULIAN: // yy/ddd
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_YEAR), 3));
+ // @F3D buffer.append(" ");
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_MDY: // mm/dd/yy
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 2));
+ // @F3D buffer.append(" ");
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_DMY: // dd/mm/yy
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 2));
+ // @F3D buffer.append(" ");
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_YMD: // yy/mm/dd
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append(separator);
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ // @F3D buffer.append(" ");
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_JIS: // yyyy-mm-dd
+ case SQLConversionSettings.DATE_FORMAT_ISO: // yyyy-mm-dd
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.YEAR), 4));
+ buffer.append('-');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.MONTH) + 1, 2));
+ buffer.append('-');
+ buffer.append(JDUtilities.padZeros(calendar.get(Calendar.DAY_OF_MONTH), 2));
+ break;
+ }
+
+ return buffer.toString();
+ }
+
+ private static int twoDigitYearToFour(int twoDigitYear)
+ {
+ return(twoDigitYear <= 39)
+ ? (twoDigitYear + 2000)
+ : (twoDigitYear + 1900);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ int connectionDateFormat = settings_.getDateFormat(); // @550A
+ // @550 If the date is in a stored procedure result set, it could have a different date format than the format of the connection
+ switch(((dateFormat_ != -1) && (dateFormat_ != connectionDateFormat)) ? dateFormat_ : connectionDateFormat) // @550C
+ {
+
+ case SQLConversionSettings.DATE_FORMAT_JULIAN: // yy/ddd
+ year_ = twoDigitYearToFour((rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f));
+ Calendar calendar = AS400Calendar.getGregorianInstance();
+ calendar.clear();
+ calendar.set(Calendar.YEAR, year_);
+ calendar.set(Calendar.DAY_OF_YEAR,
+ (rawBytes[offset+3] & 0x0f) * 100
+ + (rawBytes[offset+4] & 0x0f) * 10
+ + (rawBytes[offset+5] & 0x0f));
+ calendar.setTime(calendar.getTime());
+ month_ = calendar.get(Calendar.MONTH);
+ day_ = calendar.get(Calendar.DAY_OF_MONTH);
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_MDY: // mm/dd/yy
+ month_ = (rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f) - 1;
+ day_ = (rawBytes[offset+3] & 0x0f) * 10
+ + (rawBytes[offset+4] & 0x0f);
+ year_ = twoDigitYearToFour((rawBytes[offset+6] & 0x0f) * 10
+ + (rawBytes[offset+7] & 0x0f));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_DMY: // dd/mm/yy
+ day_ = (rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f);
+ month_ = (rawBytes[offset+3] & 0x0f) * 10
+ + (rawBytes[offset+4] & 0x0f) - 1;
+ year_ = twoDigitYearToFour((rawBytes[offset+6] & 0x0f) * 10
+ + (rawBytes[offset+7] & 0x0f));
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_YMD: // yy/mm/dd
+ year_ = twoDigitYearToFour((rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f));
+ month_ = (rawBytes[offset+3] & 0x0f) * 10
+ + (rawBytes[offset+4] & 0x0f) - 1;
+ day_ = (rawBytes[offset+6] & 0x0f) * 10
+ + (rawBytes[offset+7] & 0x0f);
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_USA: // mm/dd/yyyy
+ month_ = (rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f) - 1;
+ day_ = (rawBytes[offset+3] & 0x0f) * 10
+ + (rawBytes[offset+4] & 0x0f);
+ year_ = (rawBytes[offset+6] & 0x0f) * 1000
+ + (rawBytes[offset+7] & 0x0f) * 100
+ + (rawBytes[offset+8] & 0x0f) * 10
+ + (rawBytes[offset+9] & 0x0f);
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_ISO: // yyyy-mm-dd
+ case SQLConversionSettings.DATE_FORMAT_JIS: // yyyy-mm-dd
+ year_ = (rawBytes[offset+0] & 0x0f) * 1000
+ + (rawBytes[offset+1] & 0x0f) * 100
+ + (rawBytes[offset+2] & 0x0f) * 10
+ + (rawBytes[offset+3] & 0x0f);
+ month_ = (rawBytes[offset+5] & 0x0f) * 10
+ + (rawBytes[offset+6] & 0x0f) - 1;
+ day_ = (rawBytes[offset+8] & 0x0f) * 10
+ + (rawBytes[offset+9] & 0x0f);
+ break;
+
+ case SQLConversionSettings.DATE_FORMAT_EUR: // dd.mm.yyyy
+ day_ = (rawBytes[offset+0] & 0x0f) * 10
+ + (rawBytes[offset+1] & 0x0f);
+ month_ = (rawBytes[offset+3] & 0x0f) * 10
+ + (rawBytes[offset+4] & 0x0f) - 1;
+ year_ = (rawBytes[offset+6] & 0x0f) * 1000
+ + (rawBytes[offset+7] & 0x0f) * 100
+ + (rawBytes[offset+8] & 0x0f) * 10
+ + (rawBytes[offset+9] & 0x0f);
+ break;
+ }
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ // Always use ISO format here.
+ StringBuffer buffer = new StringBuffer(10);
+ buffer.append(JDUtilities.padZeros(year_, 4));
+ buffer.append('-');
+ buffer.append(JDUtilities.padZeros(month_ + 1, 2));
+ buffer.append('-');
+ buffer.append(JDUtilities.padZeros(day_, 2));
+
+ try
+ {
+ ccsidConverter.stringToByteArray(buffer.toString(), rawBytes, offset);
+ }
+ catch(CharConversionException e)
+ {
+ JDError.throwSQLException(JDError.EXC_INTERNAL, e); // @E2C
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ if(calendar == null)
+ {
+ calendar = AS400Calendar.getGregorianInstance(); //@P0A
+ calendar.setLenient(false); //@dat1
+ }
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+
+ if(object instanceof String)
+ {
+ stringToDate((String) object, settings_, calendar);
+ year_ = calendar.get(Calendar.YEAR);
+ month_ = calendar.get(Calendar.MONTH);
+ day_ = calendar.get(Calendar.DAY_OF_MONTH);
+ }
+
+ else if(object instanceof Timestamp)
+ { // @F5M
+ calendar.setTime((Timestamp) object);
+ year_ = calendar.get(Calendar.YEAR);
+ month_ = calendar.get(Calendar.MONTH);
+ day_ = calendar.get(Calendar.DAY_OF_MONTH);
+ }
+
+ else if(object instanceof java.util.Date)
+ { // @F5C
+ calendar.setTime((java.util.Date) object); // @F5C
+ year_ = calendar.get(Calendar.YEAR);
+ month_ = calendar.get(Calendar.MONTH);
+ day_ = calendar.get(Calendar.DAY_OF_MONTH);
+ }
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.DATE;
+ }
+
+ public String getCreateParameters()
+ {
+ return null;
+ }
+
+
+ public int getDisplaySize()
+ {
+ return 10;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.sql.Date";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return "\'";
+ }
+
+ public String getLiteralSuffix()
+ {
+ return "\'";
+ }
+
+ public String getLocalName()
+ {
+ return "DATE";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 10;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 384;
+ }
+
+ public int getPrecision()
+ {
+ return 10;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.DATE;
+ }
+
+ public String getTypeName()
+ {
+ return "DATE";
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return 10;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return false;
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(calendar == null) calendar = AS400Calendar.getGregorianInstance();
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+
+ calendar.set(year_, month_, day_, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ long millis;
+ if (jdk14) { millis =calendar.getTimeInMillis(); } else { millis = calendar.getTime().getTime(); }
+ return new Date(millis);
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return getDate(null);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ Calendar calendar = AS400Calendar.getGregorianInstance();
+ calendar.set(year_, month_, day_, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ long millis;
+ if (jdk14) { millis =calendar.getTimeInMillis(); } else { millis = calendar.getTime().getTime(); }
+ Date d = new Date(millis);
+ return dateToString(d, settings_, calendar);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(calendar == null) calendar = AS400Calendar.getGregorianInstance(); //@P0A
+ else {
+ calendar = AS400Calendar.getConversionCalendar(calendar);
+ }
+
+ calendar.set(year_, month_, day_, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ long millis;
+ if (jdk14) { millis =calendar.getTimeInMillis(); } else { millis = calendar.getTime().getTime(); }
+ Timestamp ts = new Timestamp(millis);
+ ts.setNanos(0);
+ return ts;
+ }
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ Calendar calendar = AS400Calendar.getGregorianInstance();
+ calendar.set(year_, month_, day_, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ long millis;
+ if (jdk14) { millis =calendar.getTimeInMillis(); } else { millis = calendar.getTime().getTime(); }
+ Date d = new Date(millis);
+ return dateToString(d, settings_, calendar);
+ }
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ // @array
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLDecFloat16.java b/jdbc40/com/ibm/as400/access/SQLDecFloat16.java
new file mode 100644
index 000000000..41c9e5794
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDecFloat16.java
@@ -0,0 +1,638 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+//JTOpen (IBM Toolbox for Java - OSS version)
+//
+//Filename: SQLDecFloat16.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) 2006 International Business Machines Corporation and
+//others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+//@DFA new class
+final class SQLDecFloat16 extends SQLDataBase {
+
+ private static final BigDecimal default_ = BigDecimal.valueOf(0);
+
+ //various min/max values used for comparisons in calculating truncation etc
+ private static final BigDecimal BYTE_MAX_VALUE = BigDecimal.valueOf(Byte.MAX_VALUE);
+
+ private static final BigDecimal BYTE_MIN_VALUE = BigDecimal.valueOf(Byte.MIN_VALUE);
+
+ private static final BigDecimal SHORT_MAX_VALUE = BigDecimal.valueOf(Short.MAX_VALUE);
+
+ private static final BigDecimal SHORT_MIN_VALUE = BigDecimal.valueOf(Short.MIN_VALUE);
+
+ private static final BigDecimal INTEGER_MAX_VALUE = BigDecimal.valueOf(Integer.MAX_VALUE);
+
+ private static final BigDecimal INTEGER_MIN_VALUE = BigDecimal.valueOf(Integer.MIN_VALUE);
+
+ private static final BigDecimal LONG_MAX_VALUE = BigDecimal.valueOf(Long.MAX_VALUE);
+
+ private static final BigDecimal LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
+
+ private static final BigDecimal FLOAT_MAX_VALUE = new BigDecimal(Float.MAX_VALUE);
+
+ private static final BigDecimal FLOAT_MIN_VALUE = new BigDecimal(-Float.MAX_VALUE); //@PDC MIN_VALUE is positive
+
+ private static final BigDecimal DOUBLE_MAX_VALUE = new BigDecimal(Double.MAX_VALUE);
+
+ private static final BigDecimal DOUBLE_MIN_VALUE = new BigDecimal(-Double.MAX_VALUE); //@PDC MIN_VALUE is positive
+
+ static final int DECFLOAT16_MIN_EXP = -383;
+
+
+ private int precision_; //16
+
+
+ String specialValue_ = null; //since BigDecimal cannot hold "Infinity", "-Infinity" or "NaN", store them here as string
+
+ private AS400DecFloat typeConverter_;
+
+ private BigDecimal value_;
+
+ private JDProperties properties_;
+
+ private int roundingMode;
+
+ private String roundingModeStr;
+
+ private int vrm_;
+
+ SQLDecFloat16( SQLConversionSettings settings, int vrm, JDProperties properties) {
+ super(settings);
+ precision_ = 16;
+ roundingModeStr = properties.getString(JDProperties.DECFLOAT_ROUNDING_MODE);
+ typeConverter_ = new AS400DecFloat(precision_ );
+ value_ = default_;
+ vrm_ = vrm;
+ properties_ = properties;
+
+ //parse property rounding mode and save its value as int (needed for BigDecimal, MathContext etc)
+ // valid rounding modes are:
+ //"half even"
+ //"half up"
+ //"down"
+ //"ceiling"
+ //"floor"
+ //"half down"
+ //"up"
+
+ if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_UP))
+ roundingMode = BigDecimal.ROUND_UP;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_DOWN))
+ roundingMode = BigDecimal.ROUND_DOWN;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_CEILING))
+ roundingMode = BigDecimal.ROUND_CEILING;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_FLOOR))
+ roundingMode = BigDecimal.ROUND_FLOOR;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_UP))
+ roundingMode = BigDecimal.ROUND_HALF_UP;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_DOWN))
+ roundingMode = BigDecimal.ROUND_HALF_DOWN;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_EVEN))
+ roundingMode = BigDecimal.ROUND_HALF_EVEN;
+
+
+ //for MathContext, methods take strings which are same as JDProperties rounding modes with "round" added.
+ roundingModeStr = "ROUND_" + roundingModeStr.toUpperCase().replace(' ', '_');
+
+ }
+
+ public Object clone() {
+ return new SQLDecFloat16( settings_, vrm_, properties_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccisdConverter)
+ throws SQLException {
+ try{
+ value_ = ((BigDecimal) typeConverter_.toObject(rawBytes, offset));
+ specialValue_ = null;
+ } catch (ExtendedIllegalArgumentException e) {
+ //check for NAN and INF flag exception
+ if ( (specialValue_ = getSpecialValue( e.toString())) == null )
+ throw e;
+ }
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException {
+ try {
+ if ( specialValue_ == null)
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ else
+ typeConverter_.toBytes(specialValue_, rawBytes, offset); //Nan, Infinity, -Infinity
+
+ } catch (ExtendedIllegalArgumentException e) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale) throws SQLException {
+ BigDecimal bigDecimal = null;
+ specialValue_ = null;
+
+ if (object instanceof String) {
+ try {
+ if ( (specialValue_ = getSpecialValue( (String)object)) == null ) {
+ //not one of the special values, just store as BigDecimal
+
+ // Because the string may be using a comma for the decimal separator and we are going to
+ // store the object as a Java Bigdec, we much check and change to the default '.' notation.
+ if (((String)object).indexOf(',')!=-1) {
+ bigDecimal = new BigDecimal (((String)object).replace(',', '.'));
+ } else {
+ bigDecimal = new BigDecimal((String)object);
+ }
+ }
+ } catch (NumberFormatException e) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ } catch (StringIndexOutOfBoundsException e) // jdk 1.3.x throws this
+ // instead of a NFE
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ else if (object instanceof Number) {
+ if ( (specialValue_ = getSpecialValue( object.toString())) == null ) {
+ //not one of the special values, just store as BigDecimal
+ bigDecimal = new BigDecimal(object.toString()); //convert to string so all Number types can be passed in
+ }
+ }
+
+ else if (object instanceof Boolean)
+ bigDecimal = (((Boolean) object).booleanValue() == true) ? BigDecimal.valueOf(1) : BigDecimal.valueOf(0);
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ // Round by mode if necessary.
+ truncated_ = 0; outOfBounds_ = false;
+
+ //if one of the special values, then no need to check truncation
+ if(specialValue_ != null)
+ {
+ //Nan, Infinity, -Infinity
+ value_ = null;
+ return;
+ }
+
+ //follow native and allow rounding mode to handle
+ //@pdd int otherScale = bigDecimal.scale();
+ //@pdd if(otherScale > ((-1) * DECFLOAT16_MIN_EXP)) //absolute of min_exp is max scale
+ //@pdd truncated_ += otherScale + DECFLOAT16_MIN_EXP; //diff in scales
+
+ //get precision from bigDecimal without 0's on right side
+ //@pdd int otherPrecision = SQLDataFactory.getPrecisionForTruncation(bigDecimal, 16);
+
+
+ //follow native and allow rounding mode to handle
+ //@pddif(otherPrecision > precision_)
+ //@pdd{
+ //@pdd int digits = otherPrecision - precision_;
+ //@pdd truncated_ += digits;
+ //@pdd}
+ //@pddelse
+ //@pdd truncated_ = 0; outOfBounds_ = false; // No left side truncation, report nothing
+ //@pdd // (even if there was right side truncation).
+
+ value_ = AS400DecFloat.roundByMode(bigDecimal, 16, roundingModeStr);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType() {
+ return SQLData.DECFLOAT;
+ }
+
+ public String getCreateParameters() {
+ return null;
+ }
+
+ public int getDisplaySize() {
+ return 23; //@pdc same as native
+ }
+
+
+ public String getJavaClassName() {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix() {
+ return null;
+ }
+
+ public String getLiteralSuffix() {
+ return null;
+ }
+
+ public String getLocalName() {
+ return "DECFLOAT";
+ }
+
+ public int getMaximumPrecision() {
+ return precision_;
+ }
+
+ public int getMaximumScale() {
+ return 0;
+ }
+
+ public int getMinimumScale() {
+ return 0;
+ }
+
+ public int getNativeType() {
+ return 996; //same as in SQLDataFactory.java
+ }
+
+ public int getPrecision() {
+ return precision_;
+ }
+
+ public int getRadix() {
+ return 10; //decimal base (4 bits per digit)
+ }
+
+ public int getScale() {
+ return 0;
+ }
+
+ public int getType() {
+ return java.sql.Types.OTHER;
+ }
+
+ public String getTypeName() {
+ return "DECFLOAT";
+ }
+
+ public boolean isSigned() {
+ return true;
+ }
+
+ public boolean isText() {
+ return false;
+ }
+
+ public int getActualSize() {
+ if(specialValue_ == null)
+ return SQLDataFactory.getPrecision( value_ );
+ else
+ return specialValue_.length();
+ }
+
+ public int getTruncated() {
+ return truncated_;
+ }
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale) throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when BigDecimal supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ if(scale >= 0)
+ {
+ if(scale >= value_.scale())
+ {
+ return value_.setScale(scale);
+ }
+ else
+ {
+ truncated_ = value_.scale() - scale;
+ return value_.setScale(scale, roundingMode);
+ }
+ }
+ else
+ return value_;
+ }
+
+ public InputStream getBinaryStream() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ return false; //false seems logical here
+ }
+
+ return (value_.compareTo(BigDecimal.valueOf(0)) != 0);
+ }
+
+ public byte getByte() throws SQLException {
+ //this code is similar to SQLDouble, and then in inner iff, it is like
+ // SQLDecimal
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Double("-NaN")).byteValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Double("NaN")).byteValue();
+ else
+ return (new Double(specialValue_)).byteValue();
+ }
+
+ if (value_.compareTo(BYTE_MAX_VALUE) > 0 || value_.compareTo(BYTE_MIN_VALUE) < 0) {
+ if (value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0) {
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 15; //16 bytes - 1;
+ outOfBounds_ = true;
+ } else {
+ truncated_ = 7; outOfBounds_ = true;
+ }
+ } else {
+ truncated_ = 3; outOfBounds_ = true;
+ }
+ } else {
+ truncated_ = 1; outOfBounds_ = true;
+ }
+ }
+ return value_.byteValue();
+ }
+
+ public byte[] getBytes() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Double("-NaN")).doubleValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Double("NaN")).doubleValue();
+ else
+ return (new Double(specialValue_)).doubleValue();
+ }
+
+ if (value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0) {
+ truncated_ = 8; //16 bytes - 8;
+ outOfBounds_=true;
+ }
+
+ return value_.doubleValue();
+ }
+
+ public float getFloat() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Float("-NaN")).floatValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Float("NaN")).floatValue();
+ else
+ return (new Float(specialValue_)).floatValue();
+ }
+
+ if (value_.compareTo(FLOAT_MAX_VALUE) > 0 || value_.compareTo(FLOAT_MIN_VALUE) < 0) {
+ if (value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0) {
+ truncated_ = 12; //16 bytes - 4;
+ } else {
+ truncated_ = 4;
+ }
+ }
+ return value_.floatValue();
+ }
+
+ public int getInt() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when Integer supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 12; //16 bytes - 4;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ }
+
+ return value_.intValue();
+ }
+
+ public long getLong() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when Long supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if( value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0)
+ {
+ truncated_ = 8; //16 bytes - 8;
+ outOfBounds_=true;
+ }
+ return value_.longValue();
+ }
+
+ public Object getObject() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //in this case, return String object instead of throwing exception
+ //remove this when BigDecimal supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ return specialValue_;
+ }
+
+ return value_;
+ }
+
+ public short getShort() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if (value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0) {
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 14; //16 bytes - 2;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 6; outOfBounds_=true;
+ }
+ } else {
+ truncated_ = 2; outOfBounds_=true;
+ }
+ }
+
+ return value_.shortValue();
+ }
+
+ public String getString() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ return specialValue_;
+ }
+
+ String stringRep = value_.toString();
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ /** Helper method to return string value of special values that
+ * cannot be held in current BigDecimal objects.
+ * Valid inputs = "NaN", "NAN", "+NaN", "-NaN", "QNaN", "+QNaN", "-QNaN", "SNaN", "+SNaN", "-SNaN", "INF", "+INF",
+ * "-INF", "Infinity", "+Infinity", "-Infinity"
+ */
+ private String getSpecialValue(String number){
+ //use indexOf() so that we can use this method for exception text from AS400DecFloat also
+ int startOfValue = -1;
+ //@snan
+ if ( (startOfValue = number.toUpperCase().indexOf("SNAN")) != -1 ){
+ //check for sign
+ if ( ((startOfValue > 0 ) && (number.charAt(startOfValue - 1) == '-') ) )
+ return "-SNaN"; //no representaion in Double
+ else
+ return "SNaN"; //no representaion in Double
+ }
+ else if ( (startOfValue = number.toUpperCase().indexOf("NAN")) != -1 ){
+ //check for sign
+ if ( ((startOfValue > 0 ) && (number.charAt(startOfValue - 1) == '-') )
+ || ((startOfValue > 1 ) && (number.charAt(startOfValue - 2) == '-')) )
+ return "-NaN"; //no representaion in Double
+ return String.valueOf(Double.NaN);
+ }
+ else if ( (startOfValue = number.toUpperCase().indexOf("INF")) != -1){
+ //check for sign
+ if ( (startOfValue != 0 ) && (number.charAt(startOfValue - 1) == '-'))
+ return String.valueOf(Double.NEGATIVE_INFINITY);
+ else
+ return String.valueOf(Double.POSITIVE_INFINITY);
+ }
+ else
+ return null; //not a special value
+ }
+
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ return getString();
+
+ }
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ // @array
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDecFloat34.java b/jdbc40/com/ibm/as400/access/SQLDecFloat34.java
new file mode 100644
index 000000000..de217fc83
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDecFloat34.java
@@ -0,0 +1,653 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+//JTOpen (IBM Toolbox for Java - OSS version)
+//
+//Filename: SQLDecFloat34.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) 2006 International Business Machines Corporation and
+//others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+//@DFA new class
+final class SQLDecFloat34 extends SQLDataBase {
+ static final String copyright = "Copyright (C) 2006 International Business Machines Corporation and others.";
+
+ private static final BigDecimal default_ = BigDecimal.valueOf(0);
+
+ //various min/max values used for comparisons in calculating truncation etc
+ private static final BigDecimal BYTE_MAX_VALUE = BigDecimal.valueOf(Byte.MAX_VALUE);
+
+ private static final BigDecimal BYTE_MIN_VALUE = BigDecimal.valueOf(Byte.MIN_VALUE);
+
+ private static final BigDecimal SHORT_MAX_VALUE = BigDecimal.valueOf(Short.MAX_VALUE);
+
+ private static final BigDecimal SHORT_MIN_VALUE = BigDecimal.valueOf(Short.MIN_VALUE);
+
+ private static final BigDecimal INTEGER_MAX_VALUE = BigDecimal.valueOf(Integer.MAX_VALUE);
+
+ private static final BigDecimal INTEGER_MIN_VALUE = BigDecimal.valueOf(Integer.MIN_VALUE);
+
+ private static final BigDecimal LONG_MAX_VALUE = BigDecimal.valueOf(Long.MAX_VALUE);
+
+ private static final BigDecimal LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
+
+ private static final BigDecimal FLOAT_MAX_VALUE = new BigDecimal(Float.MAX_VALUE);
+
+ private static final BigDecimal FLOAT_MIN_VALUE = new BigDecimal(-Float.MAX_VALUE); //@PDC MIN_VALUE is positive
+
+ private static final BigDecimal DOUBLE_MAX_VALUE = new BigDecimal(Double.MAX_VALUE);
+
+ private static final BigDecimal DOUBLE_MIN_VALUE = new BigDecimal(-Double.MAX_VALUE); //@PDC MIN_VALUE is positive
+
+ static final int DECFLOAT34_MIN_EXP = -6143;
+
+
+ private int precision_; //34
+
+
+ String specialValue_ = null; //since BigDecimal cannot hold "Infinity", "-Infinity" or "NaN", store them here as string
+
+ private AS400DecFloat typeConverter_;
+
+ private BigDecimal value_;
+
+ private JDProperties properties_;
+
+ private int roundingMode;
+
+ private String roundingModeStr;
+
+ private int vrm_;
+
+ SQLDecFloat34( SQLConversionSettings settings, int vrm, JDProperties properties) {
+ super(settings);
+
+ precision_ = 34;
+ roundingModeStr = properties.getString(JDProperties.DECFLOAT_ROUNDING_MODE);
+ typeConverter_ = new AS400DecFloat(precision_);
+ value_ = default_;
+ vrm_ = vrm;
+ properties_ = properties;
+
+ //parse property rounding mode and save its value as int (needed for BigDecimal, MathContext etc)
+ // valid rounding modes are:
+ //"half even"
+ //"half up"
+ //"down"
+ //"ceiling"
+ //"floor"
+ //"half down"
+ //"up"
+
+ if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_UP))
+ roundingMode = BigDecimal.ROUND_UP;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_DOWN))
+ roundingMode = BigDecimal.ROUND_DOWN;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_CEILING))
+ roundingMode = BigDecimal.ROUND_CEILING;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_FLOOR))
+ roundingMode = BigDecimal.ROUND_FLOOR;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_UP))
+ roundingMode = BigDecimal.ROUND_HALF_UP;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_DOWN))
+ roundingMode = BigDecimal.ROUND_HALF_DOWN;
+ else if ( roundingModeStr.equals(JDProperties.DECFLOAT_ROUNDING_MODE_HALF_EVEN))
+ roundingMode = BigDecimal.ROUND_HALF_EVEN;
+
+
+ //for MathContext, methods take strings which are same as JDProperties rounding modes with "round" added.
+ roundingModeStr = "ROUND_" + roundingModeStr.toUpperCase().replace(' ', '_');
+ }
+
+ public Object clone() {
+ return new SQLDecFloat34( settings_, vrm_, properties_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccisdConverter)
+ throws SQLException {
+ try{
+ value_ = ((BigDecimal) typeConverter_.toObject(rawBytes, offset));
+ specialValue_ = null;
+ } catch (ExtendedIllegalArgumentException e) {
+ //check for NAN and INF flag exception
+ if ( (specialValue_ = getSpecialValue( e.toString())) == null )
+ throw e;
+ }
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException {
+ try{
+ if ( specialValue_ == null)
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ else
+ typeConverter_.toBytes(specialValue_, rawBytes, offset); //Nan, Infinity, -Infinity
+ } catch (ExtendedIllegalArgumentException e) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale) throws SQLException {
+ BigDecimal bigDecimal = null;
+ specialValue_ = null;
+
+ if (object instanceof String) {
+ try {
+ if ( (specialValue_ = getSpecialValue( (String)object)) == null ) {
+ //not one of the special values, just store as BigDecimal
+ // Because the string may be using a comma for the decimal separator and we are going to
+ // store the object as a Java Bigdec, we much check and change to the default '.' notation.
+ if (((String)object).indexOf(',')!=-1) {
+ bigDecimal = new BigDecimal (((String)object).replace(',', '.'));
+ } else {
+ bigDecimal = new BigDecimal((String)object);
+ }
+ }
+ } catch (NumberFormatException e) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ } catch (StringIndexOutOfBoundsException e) // jdk 1.3.x throws this
+ // instead of a NFE
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ else if (object instanceof Number) {
+ if ( (specialValue_ = getSpecialValue( object.toString())) == null ) {
+ //not one of the special values, just store as BigDecimal
+ bigDecimal = new BigDecimal(object.toString()); //convert to string so all Number types can be passed in
+ }
+ }
+
+ else if (object instanceof Boolean)
+ bigDecimal = (((Boolean) object).booleanValue() == true) ? BigDecimal.valueOf(1) : BigDecimal.valueOf(0);
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ //Round by mode if necessary.
+ truncated_ = 0; outOfBounds_ = false;
+
+ //if one of the special values, then no need to check truncation
+ if(specialValue_ != null)
+ {
+ //Nan, Infinity, -Infinity
+ value_ = null;
+ return;
+ }
+
+ //follow native and allow rounding mode to handle
+ //@pdd int otherScale = bigDecimal.scale();
+ //@pdd if(otherScale > ((-1) * DECFLOAT34_MIN_EXP)) //absolute of min_exp is max scale
+ //@pdd truncated_ += otherScale + DECFLOAT34_MIN_EXP; //diff in scales
+
+ //get precision from bigDecimal without 0's on right side
+ //@pdd int otherPrecision = SQLDataFactory.getPrecisionForTruncation(bigDecimal, 34);
+
+ //follow native and allow rounding mode to handle
+ //@pdd if(otherPrecision > precision_)
+ //@pdd {
+ //@pdd int digits = otherPrecision - precision_;
+ //@pdd truncated_ += digits;
+ //@pdd }
+ //@pdd else
+ //@pdd truncated_ = 0; outOfBounds_ = false; // No left side truncation, report nothing
+ //@pdd // (even if there was right side truncation).
+
+ value_ = AS400DecFloat.roundByMode(bigDecimal, 34, roundingModeStr);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType() {
+ return SQLData.DECFLOAT;
+ }
+
+ public String getCreateParameters() {
+ return null;
+ }
+
+ public int getDisplaySize() {
+ return 42; //@pdc same as native
+ }
+
+
+ public String getJavaClassName() {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix() {
+ return null;
+ }
+
+ public String getLiteralSuffix() {
+ return null;
+ }
+
+ public String getLocalName() {
+ return "DECFLOAT";
+ }
+
+ public int getMaximumPrecision() {
+ return precision_;
+ }
+
+ public int getMaximumScale() {
+ return 0;
+ }
+
+ public int getMinimumScale() {
+ return 0;
+ }
+
+ public int getNativeType() {
+ return 996;
+ }
+
+ public int getPrecision() {
+ return precision_;
+ }
+
+ public int getRadix() {
+ return 10; //decimal base (4 bits per digit)
+ }
+
+ public int getScale() {
+ return 0;
+ }
+
+ public int getType() {
+ return java.sql.Types.OTHER; //decfloat is not sql type right now.
+ }
+
+ public String getTypeName() {
+ return "DECFLOAT";
+ }
+
+ public boolean isSigned() {
+ return true;
+ }
+
+ public boolean isText() {
+ return false;
+ }
+
+ public int getActualSize() {
+ if(specialValue_ == null)
+ return SQLDataFactory.getPrecision( value_ );
+ else
+ return specialValue_.length();
+ }
+
+ public int getTruncated() {
+ return truncated_;
+ }
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale) throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when BigDecimal supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ if(scale >= 0)
+ {
+ if(scale >= value_.scale())
+ {
+ return value_.setScale(scale);
+ }
+ else
+ {
+ truncated_ = value_.scale() - scale;
+ return value_.setScale(scale, roundingMode);
+ }
+ }
+ else
+ return value_;
+ }
+
+ public InputStream getBinaryStream() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ return false; //false seems logical here
+ }
+
+ return (value_.compareTo(BigDecimal.valueOf(0)) != 0);
+ }
+
+ public byte getByte() throws SQLException {
+ //this code is similar to SQLDouble, and then in inner iff, it is like
+ // SQLDecimal
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Double("-NaN")).byteValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Double("NaN")).byteValue();
+ else
+ return (new Double(specialValue_)).byteValue();
+ }
+
+ if (value_.compareTo(BYTE_MAX_VALUE) > 0 || value_.compareTo(BYTE_MIN_VALUE) < 0) {
+ if (value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0) {
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 15; //16 bytes - 1;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 7; outOfBounds_=true;
+ }
+ } else {
+ truncated_ = 3; outOfBounds_=true;
+ }
+ } else {
+ truncated_ = 1; outOfBounds_=true;
+ }
+ }
+ return value_.byteValue();
+ }
+
+ public byte[] getBytes() throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Double("-NaN")).doubleValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Double("NaN")).doubleValue();
+ else
+ return (new Double(specialValue_)).doubleValue();
+ }
+
+ if (value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0) {
+ truncated_ = 8; //16 bytes - 8;
+ outOfBounds_=true;
+ }
+
+ return value_.doubleValue();
+ }
+
+ public float getFloat() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ //@snan snan is not yet supported, return as regular nan
+ if(specialValue_.indexOf("-SNaN") != -1) //@snan
+ return (new Float("-NaN")).floatValue();
+ else if(specialValue_.indexOf("SNaN") != -1) //@snan
+ return (new Float("NaN")).floatValue();
+ else
+ return (new Float(specialValue_)).floatValue();
+ }
+
+ if (value_.compareTo(FLOAT_MAX_VALUE) > 0 || value_.compareTo(FLOAT_MIN_VALUE) < 0) {
+ if (value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0) {
+ truncated_ = 12; //16 bytes - 4;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ }
+ return value_.floatValue();
+ }
+
+ public int getInt() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when Integer supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 12; //16 bytes - 4;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ }
+
+ return value_.intValue();
+ }
+
+ public long getLong() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //remove this when Long supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if( value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0)
+ {
+ truncated_ = 8; //16 bytes - 8;
+ outOfBounds_=true;
+ }
+ return value_.longValue();
+ }
+
+ public Object getObject() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ //in this case, return String object instead of throwing exception
+ //remove this when BigDecimal supports Nan, Inf, -Inf
+ if(specialValue_ != null){
+ return specialValue_;
+ }
+
+ return value_;
+ }
+
+ public short getShort() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if (value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0) {
+ if (value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0) {
+ if (value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0) {
+ truncated_ = 14; //16 bytes - 2;
+ outOfBounds_=true;
+ } else {
+ truncated_ = 6;
+ outOfBounds_=true;
+ }
+ } else {
+ truncated_ = 2;
+ outOfBounds_=true;
+ }
+ }
+
+ return value_.shortValue();
+ }
+
+ public String getString() throws SQLException {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ return specialValue_;
+ }
+
+ String stringRep = value_.toString();
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar) throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ /** Helper method to return string value of special values that
+ * cannot be held in current BigDecimal objects.
+ * Valid inputs = "NaN", "NAN", "+NaN", "-NaN", "QNaN", "+QNaN", "-QNaN", "SNaN", "+SNaN", "-SNaN", "INF", "+INF",
+ * "-INF", "Infinity", "+Infinity", "-Infinity"
+ */
+ private String getSpecialValue(String number){
+ //use indexOf() so that we can use this method for exception text from AS400DecFloat also
+ int startOfValue = -1;
+ //@snan
+ if ( (startOfValue = number.toUpperCase().indexOf("SNAN")) != -1 ){
+ //check for sign
+ if ( ((startOfValue > 0 ) && (number.charAt(startOfValue - 1) == '-') ) )
+ return "-SNaN"; //no representaion in Double
+ else
+ return "SNaN"; //no representaion in Double
+ }
+ else if ( (startOfValue = number.toUpperCase().indexOf("NAN")) != -1 ){
+ //check for sign
+ if ( ((startOfValue > 0 ) && (number.charAt(startOfValue - 1) == '-') )
+ || ((startOfValue > 1 ) && (number.charAt(startOfValue - 2) == '-')) )
+ return "-NaN"; //no representaion in Double
+ return String.valueOf(Double.NaN);
+ }
+ else if ( (startOfValue = number.toUpperCase().indexOf("INF")) != -1){
+ //check for sign
+ if ( (startOfValue != 0 ) && (number.charAt(startOfValue - 1) == '-'))
+ return String.valueOf(Double.NEGATIVE_INFINITY);
+ else
+ return String.valueOf(Double.POSITIVE_INFINITY);
+ }
+ else
+ return null; //not a special value
+ }
+
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ //NaN, Infinity, -Infinity
+ if(specialValue_ != null){
+ return specialValue_;
+ }
+
+ String stringRep = value_.toString();
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDecimal.java b/jdbc40/com/ibm/as400/access/SQLDecimal.java
new file mode 100644
index 000000000..64c837dff
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDecimal.java
@@ -0,0 +1,512 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLDecimal.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.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLDecimal
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private.
+ private static final BigDecimal default_ = BigDecimal.valueOf(0); // @C2A
+ private static final BigDecimal BYTE_MAX_VALUE = BigDecimal.valueOf(Byte.MAX_VALUE);
+ private static final BigDecimal BYTE_MIN_VALUE = BigDecimal.valueOf(Byte.MIN_VALUE);
+ private static final BigDecimal SHORT_MAX_VALUE = BigDecimal.valueOf(Short.MAX_VALUE);
+ private static final BigDecimal SHORT_MIN_VALUE = BigDecimal.valueOf(Short.MIN_VALUE);
+ private static final BigDecimal INTEGER_MAX_VALUE = BigDecimal.valueOf(Integer.MAX_VALUE);
+ private static final BigDecimal INTEGER_MIN_VALUE = BigDecimal.valueOf(Integer.MIN_VALUE);
+ private static final BigDecimal LONG_MAX_VALUE = BigDecimal.valueOf(Long.MAX_VALUE);
+ private static final BigDecimal LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
+ static final BigDecimal FLOAT_MAX_VALUE = new BigDecimal(Float.MAX_VALUE);
+ static final BigDecimal FLOAT_MIN_VALUE = new BigDecimal(Float.MIN_VALUE);
+ static final BigDecimal DOUBLE_MAX_VALUE = new BigDecimal(Double.MAX_VALUE);
+ static final BigDecimal DOUBLE_MIN_VALUE = new BigDecimal(Double.MIN_VALUE);
+
+ private int precision_;
+ private int scale_;
+ private AS400PackedDecimal typeConverter_;
+ private BigDecimal value_;
+ private JDProperties properties_; // @M0A - added JDProperties so we can get the scale & precision
+ private int vrm_; // @M0A
+
+ SQLDecimal(int precision,
+ int scale,
+ SQLConversionSettings settings,
+ int vrm, // @M0C
+ JDProperties properties) // @M0C
+ {
+ super(settings);
+ precision_ = precision;
+ scale_ = scale;
+ typeConverter_ = new AS400PackedDecimal(precision_, scale_);
+ value_ = default_; // @C2C
+ vrm_ = vrm; // @M0A
+ properties_ = properties; // @M0A
+ }
+
+ public Object clone()
+ {
+ return new SQLDecimal(precision_, scale_, settings_, vrm_, properties_); // @M0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccisdConverter) //@P0C
+ throws SQLException
+ {
+ value_ = ((BigDecimal)typeConverter_.toObject(rawBytes, offset));
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ try{
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ }
+ catch(ExtendedIllegalArgumentException e){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ BigDecimal bigDecimal = null;
+
+ if(object instanceof String) {
+ try
+ {
+ String value = SQLDataFactory.convertScientificNotation((String)object, settings_); // @F3C
+ if(scale >= 0)
+ value = SQLDataFactory.truncateScale(value, scale);
+ bigDecimal = new BigDecimal(value);
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return;
+ }
+ catch(StringIndexOutOfBoundsException e) // jdk 1.3.x throws this instead of a NFE
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return;
+ }
+ } else if(object instanceof Number) {
+ String value = SQLDataFactory.convertScientificNotation(object.toString(), settings_); // @C1C
+ if(scale >= 0)
+ value = SQLDataFactory.truncateScale(value, scale);
+ bigDecimal = new BigDecimal(value);
+ } else if(object instanceof Boolean) {
+ bigDecimal = (((Boolean)object).booleanValue() == true) ? BigDecimal.valueOf(1) : BigDecimal.valueOf(0);
+
+ } else {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return;
+ }
+ // Truncate if necessary. If we ONLY truncate on the right side, we don't @E2C
+ // need to report it. If we truncate on the left side, then we report the @E2A
+ // number of truncated digits on both ends...this will make the dataSize @E2A
+ // and transferSize make sense on the resulting DataTruncation. @E2A
+ truncated_ = 0; outOfBounds_ = false;
+ int otherScale = bigDecimal.scale();
+ if(otherScale > scale_)
+ truncated_ += otherScale - scale_;
+ value_ = bigDecimal.setScale(scale_, BigDecimal.ROUND_DOWN); // @E2C
+
+ int otherPrecision = SQLDataFactory.getDecimalPrecision(value_); /*@H5C*/
+ // Check for the odd case where the precision = scale @H5C
+ if (precision_ == scale_) {
+ if (value_.intValue() == 0) {
+ otherPrecision = otherPrecision - 1;
+ }
+ }
+ if(otherPrecision > precision_)
+ {
+ int digits = otherPrecision - precision_;
+ truncated_ += digits;
+ value_ = SQLDataFactory.truncatePrecision(value_, digits);
+ }
+ else // @E2A
+ truncated_ = 0; outOfBounds_ = false; // No left side truncation, report nothing @E2A
+ // (even if there was right side truncation). @E2A
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.DECIMAL;
+ }
+
+ public String getCreateParameters()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(AS400JDBCDriver.getResource("PRECISION"));
+ buffer.append(",");
+ buffer.append(AS400JDBCDriver.getResource("SCALE"));
+ return buffer.toString();
+ }
+
+ public int getDisplaySize()
+ {
+ return precision_ + 2;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "DECIMAL";
+ }
+
+ public int getMaximumPrecision()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ else
+ return 31;
+ }
+
+ public int getMaximumScale()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ else
+ return 31;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 484;
+ }
+
+ public int getPrecision()
+ {
+ return precision_;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return scale_;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.DECIMAL;
+ }
+
+ public String getTypeName()
+ {
+ return "DECIMAL";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return precision_;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale >= 0)
+ {
+ if(scale >= value_.scale())
+ {
+ return value_.setScale(scale);
+ }
+ else
+ {
+ truncated_ = value_.scale() - scale;
+ return value_.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return value_;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_.compareTo(BigDecimal.valueOf(0)) != 0);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(BYTE_MAX_VALUE) > 0 || value_.compareTo(BYTE_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 1;
+ outOfBounds_=true;
+ }
+ return(byte) value_.byteValue();
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ double d = value_.doubleValue(); //@KBA
+ //@KBD will never occur with current precision of 63
+ //@KBD if(value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0)
+ if(d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY) //@KBA
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 8;
+ outOfBounds_=true;
+ }
+ return d; //@KBC value_.doubleValue();
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ float f = value_.floatValue(); //@KBA
+ //@KBD changed in order to avoid optimization problem in JRE 1.3
+ //@KBD if(value_.compareTo(FLOAT_MAX_VALUE) > 0 || value_.compareTo(FLOAT_MIN_VALUE) < 0)
+ if( f == Float.POSITIVE_INFINITY || f == Float.NEGATIVE_INFINITY) //@KBA
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 4;
+ outOfBounds_=true;
+ }
+ return f; //@KBC value_.floatValue();
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 4;
+ outOfBounds_=true;
+ }
+ return value_.intValue();
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 8;
+ outOfBounds_=true;
+ }
+ return value_.longValue();
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 2;
+ outOfBounds_=true;
+ }
+ return(short) value_.shortValue();
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = JDUtilities.bigDecimalToPlainString(value_); //@big java 1.5 support
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = value_.toString();
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDecimal2.java b/jdbc40/com/ibm/as400/access/SQLDecimal2.java
new file mode 100644
index 000000000..0e54a8266
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDecimal2.java
@@ -0,0 +1,441 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLDecimal2.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.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLDecimal2
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2006 International Business Machines Corporation and others.";
+
+ // Private data.
+ private int precision_;
+ private int scale_;
+ private AS400PackedDecimal typeConverter_;
+ private double value_;
+ private JDProperties properties_; // @M0A - added JDProperties so we can get the scale & precision
+ private int vrm_; // @M0A
+
+ SQLDecimal2(int precision,
+ int scale,
+ SQLConversionSettings settings,
+ int vrm, // @M0C
+ JDProperties properties) // @M0C
+ {
+ super(settings);
+ precision_ = precision;
+ scale_ = scale;
+ typeConverter_ = new AS400PackedDecimal(precision_, scale_);
+ value_ = 0;
+ vrm_ = vrm; // @M0A
+ properties_ = properties; // @M0A
+ }
+
+ public Object clone()
+ {
+ return new SQLDecimal2(precision_, scale_, settings_, vrm_, properties_); // @M0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccisdConverter) //@P0C
+ throws SQLException
+ {
+ value_ = typeConverter_.toDouble(rawBytes, offset);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ if(object instanceof String)
+ {
+ try
+ {
+ value_ = Double.valueOf((String)object).doubleValue();
+ }
+ catch(NumberFormatException nfe)
+ { // @E4A
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe); // @E4A
+ }
+ }
+
+ else if(object instanceof Number)
+ value_ = ((Number)object).doubleValue();
+
+ else if(object instanceof Boolean)
+ value_ = ((Boolean)object).booleanValue() ? 1 : 0;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.DECIMAL_USING_DOUBLE;
+ }
+
+ public String getCreateParameters()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(AS400JDBCDriver.getResource("PRECISION"));
+ buffer.append(",");
+ buffer.append(AS400JDBCDriver.getResource("SCALE"));
+ return buffer.toString();
+ }
+
+ public int getDisplaySize()
+ {
+ return precision_ + 2;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "DECIMAL";
+ }
+
+ public int getMaximumPrecision()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ else
+ return 31;
+ }
+
+ public int getMaximumScale()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ else
+ return 31;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 484;
+ }
+
+ public int getPrecision()
+ {
+ return precision_;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return scale_;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.DECIMAL;
+ }
+
+ public String getTypeName()
+ {
+ return "DECIMAL";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return precision_;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new BigDecimal(value_);
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE)
+ {
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 7; outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 3; outOfBounds_=true;
+ }
+ }
+ else
+ {
+ truncated_ = 1; outOfBounds_=true;
+ }
+ }
+ return(byte)value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Float.MAX_VALUE || value_ < -Float.MAX_VALUE) //@trunc min_val is a posative number. //Float.MIN_VALUE)
+ {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ return(float)value_;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ return(int)value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Long.MAX_VALUE || value_ < Long.MIN_VALUE)
+ {
+ truncated_ = 1; // this is not necessarily correct, but we know there is truncation
+ outOfBounds_=true;
+ }
+ return(long)value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Double(value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 6;
+ outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 2;
+ outOfBounds_=true;
+ }
+ }
+ return(short)value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Double.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Double.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+/* ifdef JDBC40 */
+
+ //@pda jdbc40
+
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLDouble.java b/jdbc40/com/ibm/as400/access/SQLDouble.java
new file mode 100644
index 000000000..118ec33ad
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLDouble.java
@@ -0,0 +1,479 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLDouble.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.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLDouble
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private double value_;
+
+ SQLDouble(SQLConversionSettings settings)
+ {
+ super(settings);
+ truncated_ = 0; outOfBounds_ = false;
+ value_ = 0.0d;
+ }
+
+ public Object clone()
+ {
+ return new SQLDouble(settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = BinaryConverter.byteArrayToDouble(rawBytes, offset); // @D0C
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ BinaryConverter.doubleToByteArray(value_, rawBytes, offset); // @D0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(object instanceof String)
+ {
+ try
+ {
+ if (settings_.getDecimalSeparator().equals(",")){
+ object = ((String) object).replace(',','.');
+ }
+
+ value_ = Double.valueOf((String) object).doubleValue();
+ // You can't test for data truncation of a number by testing
+ // the lengths of two string versions of it.
+ // Example string that should work but will fail:
+ // "4.749000000000E+00"
+ //@E2D int objectLength = ((String) object).length();
+ //@E2D int valueLength = Double.toString(value_).length();
+ //@E2D if(valueLength < objectLength)
+ //@E2D truncated_ = objectLength - valueLength;
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ // @ D9d
+ // else if(object instanceof BigDecimal) {
+ // value_ = ((BigDecimal) object).doubleValue();
+ // int objectLength = SQLDataFactory.getPrecision((BigDecimal) object);
+ // int valueLength = SQLDataFactory.getPrecision(new BigDecimal(value_));
+ // if(valueLength < objectLength)
+ // truncated_ = objectLength - valueLength;
+ // }
+
+ else if(object instanceof Number)
+ {
+ // Set the value to the right type.
+ //@bigdectrunc change to follow native driver
+ value_ = ((Number) object).doubleValue();
+ }
+
+ else if(object instanceof Boolean)
+ value_ = (((Boolean) object).booleanValue() == true) ? 1d : 0d;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.DOUBLE;
+ }
+
+ public String getCreateParameters()
+ {
+ return null;
+ }
+
+ public int getDisplaySize()
+ {
+ return 22;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.lang.Double";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ // Use "FLOAT" not "DOUBLE". See ODBC SQLGetTypeInfo().
+ return "FLOAT";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 53;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 480;
+ }
+
+ public int getPrecision()
+ {
+ return 53;
+ }
+
+ public int getRadix()
+ {
+ return 2; //@K1C Changed from 10
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.DOUBLE;
+ }
+
+ public String getTypeName()
+ {
+ return "DOUBLE";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return SQLDataFactory.getPrecision(Double.toString(value_));
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ // Convert the value to a String before creating the
+ // BigDecimal. This will create the exact BigDecimal
+ // that we want. If you pass the value directly to
+ // BigDecimal, then the value is not exact, and the
+ // scale becomes bigger than expected.
+
+ // @A0A
+ // Modified the code to deal with numbers in scientific
+ // notations. The numbers that are in scientific notation
+ // are parsed to a base (the part before 'E') and an
+ // exponent (the part after 'E'). The base is then used
+ // to construct the BigDecimal object and then the exponent
+ // is used to shift the decimal point to its rightful place.
+
+ // BigDecimal bigDecimal = new BigDecimal(Double.toString(value_)) // @A0D
+
+ truncated_ = 0; outOfBounds_ = false;
+
+ BigDecimal bigDecimal = null; // @A0A
+
+ String numString = Double.toString(value_); // @A0A
+ int eIndex = numString.indexOf("E"); // @A0A
+ if(eIndex == -1)
+ { // @A0A
+ bigDecimal = new BigDecimal(numString); // @A0A
+ } // @A0A
+ else
+ { // @A0A
+ String base = numString.substring(0, eIndex); // @A0A
+ int exponent = Integer.parseInt(numString.substring(eIndex+1)); // @A0A
+ bigDecimal = new BigDecimal(base); // @A0A
+ bigDecimal = bigDecimal.movePointRight(exponent); // @A0A
+ } // @A0A
+
+ if(scale >= 0)
+ {
+ if(scale >= bigDecimal.scale())
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return bigDecimal.setScale(scale);
+ }
+ else
+ {
+ truncated_ = bigDecimal.scale() - scale;
+ outOfBounds_=false;
+ return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return bigDecimal;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0.0d);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE)
+ {
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 7; outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 3; outOfBounds_=true;
+ }
+ }
+ else
+ {
+ truncated_ = 1; outOfBounds_=true;
+ }
+ }
+ return(byte) value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(double) value_;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(Double.isInfinite(value_)) { //@tr3a
+ truncated_ = 0; outOfBounds_ = false; //@tr3a
+ } else if(value_ > Float.MAX_VALUE || value_ < -Float.MAX_VALUE) //@trunc min_val is a posative number. //Float.MIN_VALUE) //@tr3c
+ {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ return(float) value_;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 4; outOfBounds_=true;
+ }
+ return(int) value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Long.MAX_VALUE || value_ < Long.MIN_VALUE)
+ {
+ truncated_ = 1; // this is not necessarily correct, but we know there is truncation
+ outOfBounds_=true;
+ }
+ return(long) value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Double(value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 6;
+ outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 2; outOfBounds_=true;
+ }
+ }
+ return(short) value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Double.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLFloat.java b/jdbc40/com/ibm/as400/access/SQLFloat.java
new file mode 100644
index 000000000..872a88eee
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLFloat.java
@@ -0,0 +1,487 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLFloat.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-2001 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLFloat
+extends SQLDataBase
+{
+
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private double value_;
+
+ SQLFloat(SQLConversionSettings settings)
+ {
+ super(settings);
+ value_ = 0.0d;
+ }
+
+ public Object clone()
+ {
+ return new SQLFloat(settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = BinaryConverter.byteArrayToDouble(rawBytes, offset); // @D0C
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ BinaryConverter.doubleToByteArray(value_, rawBytes, offset); // @D0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(object instanceof String)
+ {
+ try
+ {
+ value_ = Double.valueOf((String) object).doubleValue();
+ // You can't test for data truncation of a number by testing
+ // the lengths of two string versions of it.
+ // Example string that should work but will fail:
+ // "4.749000000000E+00"
+ //@E2D int objectLength = ((String) object).length();
+ //@E2D int valueLength = Double.toString(value_).length();
+ //@E2D if(valueLength < objectLength)
+ //@E2D truncated_ = objectLength - valueLength;
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ //else if(object instanceof BigDecimal) {
+ // value_ = ((BigDecimal) object).doubleValue();
+ // int objectLength = SQLDataFactory.getPrecision((BigDecimal) object);
+ // int valueLength = SQLDataFactory.getPrecision(new BigDecimal(value_));
+ // if(valueLength < objectLength)
+ // truncated_ = objectLength - valueLength;
+ //}
+
+ else if(object instanceof Number)
+ {
+ // Set the value to the right type.
+ value_ = ((Number) object).doubleValue(); // @D9c
+
+ // Get the whole number portion of that value.
+ //long value = (long) value_; // @D9a //@bigdectrunc change to follow native driver
+
+ // Get the original value as a long. This is the
+ // largest precision we can test for for a truncation.
+ // long truncTest = ((Number) object).longValue(); // @D9a //@bigdectrunc
+
+ // If they are not equal, then we truncated significant
+ // data from the original value the user wanted us to insert.
+ //if(truncTest != value) // @D9a //@bigdectrunc
+ //truncated_ = 1; //@bigdectrunc
+ }
+
+ else if(object instanceof Boolean)
+ value_ = (((Boolean) object).booleanValue() == true) ? 1d : 0d;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.FLOAT;
+ }
+
+ public String getCreateParameters()
+ {
+ return null;
+ }
+
+ public int getDisplaySize()
+ {
+ return 22;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.lang.Float";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "FLOAT";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 53;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 480;
+ }
+
+ public int getPrecision()
+ {
+ return 53;
+ }
+
+ public int getRadix()
+ {
+ return 2; //@K1C changed from 10
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.FLOAT;
+ }
+
+ public String getTypeName()
+ {
+ return "FLOAT";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return SQLDataFactory.getPrecision(Double.toString(value_));
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ // Convert the value to a String before creating the
+ // BigDecimal. This will create the exact BigDecimal
+ // that we want. If you pass the value directly to
+ // BigDecimal, then the value is not exact, and the
+ // scale becomes bigger than expected.
+
+ // @A0A
+ // Modified the code to deal with numbers in scientific
+ // notations. The numbers that are in scientific notation
+ // are parsed to a base (the part before 'E') and an
+ // exponent (the part after 'E'). The base is then used
+ // to construct the BigDecimal object and then the exponent
+ // is used to shift the decimal point to its rightful place.
+
+ // BigDecimal bigDecimal = new BigDecimal(Double.toString(value_)) // @A0D
+
+ truncated_ = 0; outOfBounds_ = false;
+
+ BigDecimal bigDecimal = null; // @A0A
+
+ String numString = Double.toString(value_); // @A0A
+ int eIndex = numString.indexOf("E"); // @A0A
+ if(eIndex == -1)
+ { // @A0A
+ bigDecimal = new BigDecimal(numString); // @A0A
+ } // @A0A
+ else
+ { // @A0A
+ String base = numString.substring(0, eIndex); // @A0A
+ int exponent = Integer.parseInt(numString.substring(eIndex+1)); // @A0A
+ bigDecimal = new BigDecimal(base); // @A0A
+ bigDecimal = bigDecimal.movePointRight(exponent); // @A0A
+ } // @A0A
+
+ if(scale >= 0)
+ {
+ if(scale >= bigDecimal.scale())
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return bigDecimal.setScale(scale);
+ }
+ else
+ {
+ truncated_ = bigDecimal.scale() - scale;
+ return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return bigDecimal;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0.0d);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE)
+ {
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ truncated_ = 3; outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 1; outOfBounds_=true;
+ }
+ }
+ return(byte) value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Reader getCharacterStream()
+ throws SQLException
+ {
+ return new java.io.StringReader(getString());
+
+ }
+
+ public Clob getClob()
+ throws SQLException
+ {
+ String string = getString();
+ return new AS400JDBCClob(string, string.length());
+ }
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(double) value_;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(float) value_;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 1; // this may not be accurate but we know truncation will occur
+ outOfBounds_=true;
+ }
+ return(int) value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Long.MAX_VALUE || value_ < Long.MIN_VALUE)
+ {
+ truncated_ = 1; // this is not necessarily correct, but we know there is truncation
+ outOfBounds_=true;
+ }
+ return(long) value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Double(value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 3;
+ outOfBounds_=true;
+ }
+ else
+ {
+ truncated_ = 2;
+ outOfBounds_=true;
+ }
+ }
+ return(short) value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Double.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+ // @array
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLGraphic.java b/jdbc40/com/ibm/as400/access/SQLGraphic.java
new file mode 100644
index 000000000..146c0e65b
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLGraphic.java
@@ -0,0 +1,451 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLGraphic.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.CharConversionException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.sql.Blob;
+import java.sql.Clob;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.net.URL;
+
+final class SQLGraphic
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private int maxLength_;
+ private String value_;
+ private String originalValue_;
+ private int ccsid_; //@cca1
+
+ SQLGraphic(int maxLength, SQLConversionSettings settings, int ccsid) //@cca1
+ {
+ super(settings);
+ maxLength_ = maxLength;
+ value_ = "";
+ originalValue_ = "";
+ ccsid_ = ccsid; //@cca1
+ }
+
+ public Object clone()
+ {
+ return new SQLGraphic(maxLength_, settings_, ccsid_); //@cca1
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ int bidiStringType = settings_.getBidiStringType();
+
+ // if bidiStringType is not set by user, use ccsid to get value
+ if(bidiStringType == -1)
+ bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType); //@KBA
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering()); //@KBA
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering()); //@KBA
+
+ value_ = ccsidConverter.byteArrayToString(rawBytes, offset, maxLength_, bidiConversionProperties); //@KBC changed to use bidiConversionProperties instead of bidiStringType
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ // We originally padded with a single byte space. We now have the
+ // ccsid so we can figure out if that was right or not. If we should
+ // have use the double byte space, re-pad.
+ int ccsid = ccsidConverter.getCcsid();
+ if(ccsid != 13488 && ccsid != 1200)
+ {
+ int valueLength = originalValue_.length();
+ int exactLength = getDisplaySize();
+ if(valueLength < exactLength)
+ {
+ StringBuffer buffer = new StringBuffer(originalValue_);
+ char c = '\u3000';
+ for(int i = valueLength; i < exactLength; ++i)
+ buffer.append(c);
+ value_ = buffer.toString();
+ }
+ }
+
+ int bidiStringType = settings_.getBidiStringType();
+
+ // if bidiStringType is not set by user, use ccsid to get value
+ if(bidiStringType == -1)
+ bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType); //@KBA
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering()); //@KBA
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering()); //@KBA
+
+ try
+ {
+ ccsidConverter.stringToByteArray(value_, rawBytes, offset, maxLength_, bidiConversionProperties); //@KBC changed to use bidiConversionProperties instead of bidiStringType
+ }
+ catch(CharConversionException e)
+ {
+ maxLength_ = ccsidConverter.stringToByteArray(value_, bidiConversionProperties).length; //@KBC changed to use bidiConversionProperties instead of bidiStringType
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ String value = null;
+
+ if(object instanceof String)
+ value = (String) object;
+
+ else if(object instanceof Number)
+ value = object.toString();
+
+ else if(object instanceof Boolean)
+ {
+ // @PDC
+ // if "translate boolean" == false, then use "0" and "1" values to match native driver
+ if(settings_.getTranslateBoolean() == true)
+ value = object.toString(); //"true" or "false"
+ else
+ value = ((Boolean)object).booleanValue() == true ? "1" : "0";
+ }
+
+ else if(object instanceof Time)
+ value = SQLTime.timeToString((Time) object, settings_, calendar);
+
+ else if(object instanceof Timestamp)
+ value = SQLTimestamp.timestampToStringTrimTrailingZeros((Timestamp) object, calendar);
+
+ else if(object instanceof java.util.Date)
+ value = SQLDate.dateToString((java.util.Date) object, settings_, calendar);
+
+ else if(object instanceof URL)
+ value = object.toString();
+
+ else if(JDUtilities.JDBCLevel_ >= 20 && object instanceof Clob)
+ {
+ Clob clob = (Clob)object;
+ value = clob.getSubString(1, (int)clob.length());
+ }
+/* ifdef JDBC40 */
+ else if(object instanceof SQLXML) //@PDA jdbc40
+ {
+ SQLXML xml = (SQLXML)object;
+ value = xml.getString();
+ }
+/* endif */
+
+ if(value == null)
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ value_ = value;
+ originalValue_ = value;
+
+
+ // Set to the exact length.
+ int valueLength = value_.length();
+ int exactLength = getDisplaySize();
+ if(valueLength < exactLength)
+ {
+ StringBuffer buffer = new StringBuffer(value_);
+ char c = '\u0020';
+ for(int i = valueLength; i < exactLength; ++i)
+ buffer.append(c);
+ value_ = buffer.toString();
+ truncated_ = 0; outOfBounds_ = false;
+ }
+ else if(valueLength > exactLength)
+ {
+ value_ = value_.substring(0, exactLength);
+ truncated_ = valueLength - exactLength;
+ }
+ else
+ truncated_ = 0; outOfBounds_ = false;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.GRAPHIC;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ if(ccsid_ == 65535) //@bingra
+ return maxLength_; //@bingra
+ else
+ return maxLength_ / 2;
+ }
+
+ public String getJavaClassName()
+ {
+ return "java.lang.String";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return "\'";
+ }
+
+ public String getLiteralSuffix()
+ {
+ return "\'";
+ }
+
+ public String getLocalName()
+ {
+ return "GRAPHIC";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 16382;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 468;
+ }
+
+ public int getPrecision()
+ {
+ /* maxLength_ is the length in bytes */
+ return maxLength_ / 2 ;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.CHAR;
+ }
+
+ public String getTypeName()
+ {
+ if( ccsid_ == 13488 || ccsid_ == 1200) //@cca1
+ return "NCHAR"; //@cca1 same as native
+ return "GRAPHIC";
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return value_.length();
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new HexReaderInputStream(new StringReader(getString()));
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return new AS400JDBCBlob(BinaryConverter.stringToBytes(getString()), maxLength_);
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this field contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return BinaryConverter.stringToBytes(getString());
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this field contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // This is written in terms of getString(), since it will
+ // handle truncating to the max field size if needed.
+ return getString();
+ }
+
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // Truncate to the max field size if needed.
+ // Do not signal a DataTruncation per the spec.
+ int maxFieldSize = settings_.getMaxFieldSize();
+ if((value_.length() > maxFieldSize) && (maxFieldSize > 0))
+ {
+ return value_.substring(0, maxFieldSize);
+ }
+ else
+ {
+ return value_;
+ }
+ }
+
+
+ // Added method trim() to trim the string.
+ public void trim()
+ {
+ value_ = value_.trim();
+ }
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ // Truncate to the max field size if needed.
+ // Do not signal a DataTruncation per the spec.
+ int maxFieldSize = settings_.getMaxFieldSize();
+ if((value_.length() > maxFieldSize) && (maxFieldSize > 0))
+ {
+ return value_.substring(0, maxFieldSize);
+ }
+ else
+ {
+ return value_;
+ }
+ }
+
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ //
+ //truncated_ = 0; outOfBounds_ = false;
+ //try
+ //{
+ // return new AS400JDBCRowId(BinaryConverter.stringToBytes(value_));
+ //}
+ //catch(NumberFormatException nfe)
+ //{
+ // this string contains non-hex characters
+ // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ // return null;
+ //}
+
+ //decided this is of no use
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public SQLXML getSQLXML() throws SQLException
+ {
+ //This is written in terms of getString(), since it will
+ // handle truncating to the max field size if needed.
+ truncated_ = 0; outOfBounds_ = false;
+ return new AS400JDBCSQLXML(getString());
+ }
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLInteger.java b/jdbc40/com/ibm/as400/access/SQLInteger.java
new file mode 100644
index 000000000..140c1b789
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLInteger.java
@@ -0,0 +1,516 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLInteger.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.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLInteger
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private int value_;
+ private int scale_; // @A0A
+ private BigDecimal bigDecimalValue_ = null; // @A0A
+ private int vrm_; //trunc3
+
+ SQLInteger(int vrm, SQLConversionSettings settings) //@trunc3
+ {
+ this(0, vrm, settings); //@trunc3
+ }
+
+ SQLInteger(int scale, int vrm, SQLConversionSettings settings) // @A0A //@trunc3
+ {
+ super(settings);
+
+ value_ = 0;
+ scale_ = scale; // @A0A
+ if(scale_ > 0) // @C0A
+ bigDecimalValue_ = new BigDecimal(Integer.toString(value_)); // @A0A
+ vrm_ = vrm; //@trunc3
+ }
+
+ public Object clone()
+ {
+ return new SQLInteger(scale_, vrm_, settings_); //@trunc3
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = BinaryConverter.byteArrayToInt(rawBytes, offset); // @D0C
+
+ if(scale_ > 0)
+ { // @C0A
+ bigDecimalValue_ = (new BigDecimal(Integer.toString(value_))).movePointLeft(scale_); // @A0A
+ value_ = bigDecimalValue_.intValue(); // @A0A
+ } // @C0A
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ BinaryConverter.intToByteArray(value_, rawBytes, offset); // @D0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false; // @D9c
+
+ if(object instanceof String)
+ {
+ // @D10c new implementation
+ // old ...
+ //
+ // try
+ // {
+ // value_ = Integer.parseInt((String) object);
+ // }
+ // catch(NumberFormatException e)
+ // {
+ // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ // }
+ //
+ // new ...
+
+ // First try to convert the string to an int (no extra object creation). If
+ // that fails try turning it into a Double, which will involve an extra object
+ // create but Double will accept bigger numbers and floating point numbers so it
+ // will catch more truncation cases. The bottom line is don't create an extra
+ // object in the normal case. If the user does ps.setString(1, "111222333.444.555")
+ // on an integer field, they can't expect the best performance.
+ boolean tryAgain = false;
+
+ try
+ {
+ // long longValue = (long) Double.parseDouble((String) object);
+ long longValue = (long) Long.parseLong((String) object);
+
+ if(( longValue > Integer.MAX_VALUE ) || ( longValue < Integer.MIN_VALUE ))
+ {
+ truncated_ = 4; // @D9c
+ outOfBounds_=true;
+ //@trunc3 match native for ps.setString() to throw mismatch instead of truncation
+ if(vrm_ >= JDUtilities.vrm610) //@trunc3
+ { //@trunc3
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); //@trunc3
+ } //@trunc3
+ }
+ value_ = (int) longValue;
+ }
+ catch(NumberFormatException e)
+ {
+ tryAgain = true; // a
+ // d JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ if(tryAgain) // a
+ {
+ // a
+ try // a
+ {
+ // a
+ double doubleValue = Double.valueOf((String) object).doubleValue(); // a
+ // a
+ if(( doubleValue > Integer.MAX_VALUE ) || ( doubleValue < Integer.MIN_VALUE )) // a
+ {
+ // a
+ truncated_ = 4; // a
+ outOfBounds_=true;
+ //@trunc3 match native for ps.setString() to throw mismatch instead of truncation
+ if(vrm_ >= JDUtilities.vrm610) //@trunc3
+ { //@trunc3
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); //@trunc3
+ } //@trunc3
+ } // a
+ value_ = (int) doubleValue; // a
+ } // a
+ catch(NumberFormatException e) // a
+ {
+ // a
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH); // a
+ } // a
+ } // a
+ }
+
+ else if(object instanceof Number)
+ {
+ // Compute truncation by getting the value as a long
+ // and comparing it against MAX_VALUE/MIN_VALUE. You
+ // do this because truncation of the decimal portion of
+ // the value is insignificant. We only care if the
+ // whole number portion of the value is too large/small
+ // for the column.
+ long longValue = ((Number) object).longValue(); // @D9c
+ if(( longValue > Integer.MAX_VALUE ) || ( longValue < Integer.MIN_VALUE )) // @D9c
+ {
+ // Note: Truncated here is set to 4 bytes. This is based on
+ // the idea that a long was used and an int was the
+ // column type. We could check for different types
+ // and provide a more accurate number, but I don't
+ // really know that this field is of any use to people
+ // in this case anyway (for example, you could have a
+ // float (4 bytes) that didn't fit into a bigint (8
+ // bytes) without some data truncation.
+ truncated_ = 4; // @D9c
+ outOfBounds_=true;
+ }
+
+ // Store the value.
+ value_ = (int) longValue; // @D9c
+ }
+
+ else if(object instanceof Boolean)
+ value_ = (((Boolean) object).booleanValue() == true) ? 1 : 0;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ if(scale_ > 0)
+ { // @C0A
+ bigDecimalValue_ = (new BigDecimal(Integer.toString(value_))).movePointLeft(scale_); // @A0A
+ value_ = bigDecimalValue_.intValue(); // @A0A
+ } // @C0A
+ }
+
+ public void set(int value) // @E2A
+ { // @E2A
+ value_ = value; // @E2A
+ } // @E2A
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.INTEGER;
+ }
+
+ public String getCreateParameters()
+ {
+ return null;
+ }
+
+ public int getDisplaySize()
+ {
+ return 11;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.lang.Integer";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "INTEGER";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 10;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 496;
+ }
+
+ public int getPrecision()
+ {
+ return 10;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return scale_;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.INTEGER;
+ }
+
+ public String getTypeName()
+ {
+ return "INTEGER";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return 4; // @D0C
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale_ > 0)
+ { // @C0A
+ if(scale >= 0)
+ return bigDecimalValue_.setScale(scale); // @A0A
+ else
+ return bigDecimalValue_;
+ } // @C0A
+ else
+ { // @C0A
+ if(scale <= 0) // @C0A
+ return BigDecimal.valueOf((long) value_); // @C0A
+ else // @C0A
+ return BigDecimal.valueOf((long) value_).setScale(scale); // @C0A
+ } // @C0A
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE)
+ {
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ truncated_ = 3; outOfBounds_ = true;
+ }
+ else
+ {
+ truncated_ = 1; outOfBounds_ = true;
+ }
+ }
+ return(byte) value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale_ > 0) // @C0A
+ return bigDecimalValue_.doubleValue(); // @A0A
+ else // @C0A
+ return(double) value_; // @A0D @C0A
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale_ > 0) // @C0A
+ return bigDecimalValue_.floatValue(); // @A0A
+ else // @C0A
+ return(float) value_; // @A0D @C0A
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Integer((int) value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ truncated_ = 2; outOfBounds_ = true;
+ }
+ return(short) value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale_ > 0) // @C0A
+ return bigDecimalValue_.toString(); // @A0A
+ else // @C0A
+ return Integer.toString(value_); // @A0D @C0A
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale_ > 0)
+ return bigDecimalValue_.toString();
+ else
+ return Integer.toString(value_);
+ }
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+ // @array
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLLongNVarchar.java b/jdbc40/com/ibm/as400/access/SQLLongNVarchar.java
new file mode 100644
index 000000000..48e8a0079
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLLongNVarchar.java
@@ -0,0 +1,139 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLLongNVarchar.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) 2006-2014 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.io.StringReader;
+import java.sql.Blob;
+import java.sql.Clob;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+//@PDA jdbc40 new class
+
+final class SQLLongNVarchar
+extends SQLVarcharBase implements SQLVariableCompressible
+{
+
+ // Private data.
+
+ // Note: maxLength is in bytes not counting 2 for LL.
+ //
+ SQLLongNVarchar(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings,0,maxLength,"");
+ }
+
+ public Object clone()
+ {
+ return new SQLLongNVarchar(maxLength_, settings_); //@pdc
+ }
+
+
+
+
+
+
+
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.LONG_NVARCHAR;
+ }
+
+
+
+
+ public String getLocalName()
+ {
+ return "LONGNVARCHAR";
+ }
+
+
+ public int getNativeType()
+ {
+ return 456;
+ }
+
+
+ public int getType()
+ {
+/* ifdef JDBC40 */
+ return java.sql.Types.LONGNVARCHAR;
+/* endif */
+/* ifndef JDBC40
+ return java.sql.Types.LONGVARCHAR;
+ endif */
+
+
+ }
+
+ public String getTypeName()
+ {
+/* ifdef JDBC40 */
+ return "LONGNVARCHAR";
+/* endif */
+/* ifndef JDBC40
+ return "LONGVARCHAR";
+ endif */
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+
+
+
+
+
+
+
+
+
+
+/* ifdef JDBC40 */
+
+
+ public SQLXML getSQLXML() throws SQLException
+ {
+ //This is written in terms of getString(), since it will
+ // handle truncating to the max field size if needed.
+ truncated_ = 0; outOfBounds_ = false;
+ return new AS400JDBCSQLXML(getString());
+ }
+
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLLongVarchar.java b/jdbc40/com/ibm/as400/access/SQLLongVarchar.java
new file mode 100644
index 000000000..62c7084e9
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLLongVarchar.java
@@ -0,0 +1,67 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLLongVarchar.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+
+final class SQLLongVarchar
+extends SQLVarcharBase implements SQLVariableCompressible
+{
+ static final String copyright = "Copyright (C) 1997-2013 International Business Machines Corporation and others.";
+
+
+ // Note: maxLength is in bytes not counting 2 for LL.
+ //
+ SQLLongVarchar(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings, 0, maxLength, "");
+ }
+
+ public Object clone()
+ {
+ return new SQLLongVarchar(maxLength_, settings_); //@pdc
+ }
+
+
+
+
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.LONG_VARCHAR;
+ }
+
+
+ public int getNativeType()
+ {
+ return 456;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+
+
+
+
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLLongVarcharForBitData.java b/jdbc40/com/ibm/as400/access/SQLLongVarcharForBitData.java
new file mode 100644
index 000000000..475325c1d
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLLongVarcharForBitData.java
@@ -0,0 +1,566 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLLongVarcharForBitData.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLLongVarcharForBitData
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private static final byte[] default_ = new byte[0]; // @C2A
+
+ private int length_;
+ private int maxLength_;
+ private byte[] value_;
+
+ SQLLongVarcharForBitData(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings);
+ length_ = 0;
+ maxLength_ = maxLength;
+ value_ = default_; // @C2C
+ }
+
+ public Object clone()
+ {
+ return new SQLLongVarcharForBitData(maxLength_, settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ length_ = BinaryConverter.byteArrayToUnsignedShort(rawBytes, offset);
+ AS400ByteArray typeConverter = new AS400ByteArray(length_);
+ value_ = (byte[])typeConverter.toObject(rawBytes, offset+2);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ AS400ByteArray typeConverter = new AS400ByteArray(length_);
+ BinaryConverter.unsignedShortToByteArray(length_, rawBytes, offset);
+ typeConverter.toBytes(value_, rawBytes, offset + 2);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ if(object instanceof String)
+ {
+ try
+ {
+ value_ = BinaryConverter.stringToBytes((String)object); //@F1A
+ }
+ catch(NumberFormatException nfe)
+ {
+ // the String contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ }
+ }
+
+ else if(object instanceof byte[])
+ value_ = (byte[])object; // @C1C
+
+ else if(object instanceof InputStream)
+ {
+ //value_ = JDUtilities.streamToBytes((InputStream)object, scale);
+
+ int length = scale; // hack to get the length into the set method
+ if(length >= 0)
+ {
+ InputStream stream = (InputStream)object;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ byte[] byteBuffer = new byte[blockSize];
+ try
+ {
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 && totalBytesRead < length)
+ {
+ baos.write(byteBuffer, 0, bytesRead);
+ totalBytesRead += bytesRead;
+ int bytesRemaining = length - totalBytesRead;
+ if(bytesRemaining < blockSize)
+ {
+ blockSize = bytesRemaining;
+ }
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ value_ = baos.toByteArray();
+ if(value_.length < length)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ else if(length == -2) //@readerlen new else-if block (read all data)
+ {
+ InputStream stream = (InputStream)object;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ byte[] byteBuffer = new byte[blockSize];
+ try
+ {
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 )
+ {
+ baos.write(byteBuffer, 0, bytesRead);
+ totalBytesRead += bytesRead;
+
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ value_ = baos.toByteArray();
+
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ else if(object instanceof Reader)
+ {
+ // value_ = BinaryConverter.stringToBytes(JDUtilities.readerToString((Reader)object, scale));
+
+ int length = scale; // hack to get the length into the set method
+ if(length >= 0)
+ {
+ try
+ {
+ int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ HexReaderInputStream stream = new HexReaderInputStream((Reader)object);
+ byte[] byteBuffer = new byte[blockSize];
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 && totalBytesRead < length)
+ {
+ baos.write(byteBuffer, 0, bytesRead);
+ totalBytesRead += bytesRead;
+ int bytesRemaining = length - totalBytesRead;
+ if(bytesRemaining < blockSize)
+ {
+ blockSize = bytesRemaining;
+ }
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+ value_ = baos.toByteArray();
+ stream.close(); //@scan1
+
+ if(value_.length < length)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ catch(ExtendedIOException eie)
+ {
+ // the Reader contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, eie);
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else if(length == -2) //@readerlen new else-if block (read all data)
+ {
+ try
+ {
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ HexReaderInputStream stream = new HexReaderInputStream((Reader)object);
+ byte[] byteBuffer = new byte[blockSize];
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1)
+ {
+ baos.write(byteBuffer, 0, bytesRead);
+ totalBytesRead += bytesRead;
+
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+ value_ = baos.toByteArray();
+ stream.close(); //@scan1
+
+ }
+ catch(ExtendedIOException eie)
+ {
+ // the Reader contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, eie);
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ else if(JDUtilities.JDBCLevel_ >= 20 && object instanceof Blob)
+ value_ = ((Blob)object).getBytes(1, (int)((Blob)object).length()); // @C1C @E2C Blobs are 1 based.
+
+ else if(JDUtilities.JDBCLevel_ >= 20 && object instanceof Clob)
+ {
+ try
+ {
+ value_ = BinaryConverter.stringToBytes(((Clob)object).getSubString(1, (int)((Clob)object).length())); //@F1A
+ }
+ catch(NumberFormatException nfe)
+ {
+ // the Clob contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ }
+ }
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ // Truncate if necessary.
+ int valueLength = value_.length;
+ if(valueLength > maxLength_)
+ {
+ byte[] newValue = new byte[maxLength_];
+ System.arraycopy(value_, 0, newValue, 0, maxLength_);
+ value_ = newValue;
+ truncated_ = valueLength - maxLength_;
+ outOfBounds_ = false;
+ }
+ else
+ truncated_ = 0; outOfBounds_ = false;
+
+ length_ = value_.length;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.LONG_VARCHAR_FOR_BIT_DATA;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ return maxLength_ ;
+ }
+
+ //@F2A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "[B";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return "X\'";
+ }
+
+ public String getLiteralSuffix()
+ {
+ return "\'";
+ }
+
+ public String getLocalName()
+ {
+ return "LONG VARCHAR";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 32739;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 456;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.LONGVARBINARY;
+ }
+
+ public String getTypeName()
+ {
+ return "LONG VARCHAR FOR BIT DATA";
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return value_.length;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // This is written in terms of getBytes(), since it will
+ // handle truncating to the max field size if needed.
+ return new ByteArrayInputStream(getBytes());
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // This is written in terms of getBytes(), since it will
+ // handle truncating to the max field size if needed.
+ return new AS400JDBCBlob(getBytes(), maxLength_);
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return false;
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public byte[] getBytes()
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // Truncate to the max field size if needed.
+ // Do not signal a DataTruncation per the spec. @B1A
+ int maxFieldSize = settings_.getMaxFieldSize();
+ if((value_.length > maxFieldSize) && (maxFieldSize > 0))
+ {
+ // @B1D truncated_ = value_.length - maxFieldSize;
+ byte[] truncatedValue = new byte[maxFieldSize];
+ System.arraycopy(value_, 0, truncatedValue, 0, maxFieldSize);
+ return truncatedValue;
+ }
+ else
+ {
+ // @B1D truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+ }
+
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // This is written in terms of getBytes(), since it will
+ // handle truncating to the max field size if needed.
+ return getBytes();
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return -1;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // This is written in terms of getBytes(), since it will
+ // handle truncating to the max field size if needed.
+ //@F1D return new String(getBytes());
+ return BinaryConverter.bytesToHexString(getBytes()); //@F1A
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+/* ifdef JDBC40 */
+ //@PDA jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@PDA jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLLongVargraphic.java b/jdbc40/com/ibm/as400/access/SQLLongVargraphic.java
new file mode 100644
index 000000000..f092f1ac9
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLLongVargraphic.java
@@ -0,0 +1,101 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLLongVargraphic.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+
+final class SQLLongVargraphic
+extends SQLVarcharBase implements SQLVariableCompressible
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+
+ // Note: maxLength is in bytes not counting 2 for LL.
+ //
+ SQLLongVargraphic(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings, 0, maxLength, "", 2);
+ }
+
+ public Object clone()
+ {
+ return new SQLLongVargraphic(maxLength_, settings_);
+ }
+
+
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.LONG_VARGRAPHIC;
+ }
+
+
+ public int getDisplaySize()
+ {
+ return maxLength_ / 2;
+ }
+
+
+ public String getLocalName()
+ {
+ return "LONG VARGRAPHIC";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 16369;
+ }
+
+
+ public int getNativeType()
+ {
+ return 472;
+ }
+
+ public int getPrecision()
+ {
+ // maxLength_ is in bytes;
+ return maxLength_ / 2;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.LONGVARCHAR;
+ }
+
+ public String getTypeName()
+ {
+ return "LONG VARGRAPHIC";
+ }
+
+
+
+
+
+
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNChar.java b/jdbc40/com/ibm/as400/access/SQLNChar.java
new file mode 100644
index 000000000..4ba6b0cbb
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNChar.java
@@ -0,0 +1,429 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNChar.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.CharConversionException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.sql.Blob;
+import java.sql.Clob;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.net.URL;
+
+//@PDA jdbc40 new class
+final class SQLNChar
+extends SQLDataBase
+{
+
+ // Private data.
+ private int maxLength_;
+ private String value_;
+
+ SQLNChar(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings);
+ maxLength_ = maxLength;
+ truncated_ = 0; outOfBounds_ = false;
+ value_ = "";
+ }
+
+ public Object clone()
+ {
+ return new SQLNChar(maxLength_,settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ int bidiStringType = settings_.getBidiStringType();
+
+ // if bidiStringType is not set by user, use ccsid to get value
+ if(bidiStringType == -1)
+ bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ value_ = ccsidConverter.byteArrayToString(rawBytes, offset, maxLength_, bidiConversionProperties);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ int bidiStringType = settings_.getBidiStringType();
+
+ // if bidiStringType is not set by user, use ccsid to get value
+ if(bidiStringType == -1)
+ bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ try
+ {
+ // check for truncation after conversion @H2C
+ truncated_ = ccsidConverter.stringToByteArray(value_, rawBytes, offset, maxLength_, bidiConversionProperties);
+ }
+ catch(CharConversionException e)
+ {
+ maxLength_ = ccsidConverter.stringToByteArray(value_, bidiConversionProperties).length;
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e, "Change Descriptor");
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ String value = null;
+
+ if(object instanceof String)
+ value = (String)object;
+
+ else if(object instanceof Character)
+ value = object.toString();
+
+ else if(object instanceof Number)
+ value = object.toString();
+
+ else if(object instanceof Boolean)
+ {
+ // if "translate boolean" == false, then use "0" and "1" values to match native driver
+ if(settings_.getTranslateBoolean() == true)
+ value = object.toString(); //"true" or "false"
+ else
+ value = ((Boolean)object).booleanValue() == true ? "1" : "0";
+ }
+ else if(object instanceof Time)
+ value = SQLTime.timeToString((Time)object, settings_, calendar);
+
+ else if(object instanceof Timestamp)
+ value = SQLTimestamp.timestampToStringTrimTrailingZeros((Timestamp)object, calendar);
+
+ else if(object instanceof java.util.Date)
+ value = SQLDate.dateToString((java.util.Date)object, settings_, calendar);
+
+ else if(object instanceof URL)
+ value = object.toString();
+
+ else if(JDUtilities.JDBCLevel_ >= 20 && object instanceof Clob)
+ {
+ Clob clob = (Clob)object;
+ value = clob.getSubString(1, (int)clob.length());
+ }
+
+ if(value == null)
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ value_ = value;
+
+ // Set to the exact length.
+ int valueLength = value_.length();
+ int exactLength = getDisplaySize();
+ if(valueLength < exactLength)
+ {
+ StringBuffer buffer = new StringBuffer(value_);
+ char c = '\u0020';
+ for(int i = valueLength; i < exactLength; ++i)
+ buffer.append(c);
+ value_ = buffer.toString();
+ truncated_ = 0; outOfBounds_ = false;
+ }
+ else if(valueLength > exactLength)
+ {
+ value_ = value_.substring(0, exactLength);
+ truncated_ = valueLength - exactLength;
+ outOfBounds_ = false;
+ }
+ else
+ truncated_ = 0; outOfBounds_ = false;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NCHAR;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ return maxLength_;
+ }
+
+ // JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.lang.String";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return "\'";
+ }
+
+ public String getLiteralSuffix()
+ {
+ return "\'";
+ }
+
+ public String getLocalName()
+ {
+ return "NCHAR";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 32765;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 452;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+/* ifdef JDBC40 */
+ return java.sql.Types.NCHAR;
+/* endif */
+/* ifndef JDBC40
+ return java.sql.Types.CHAR;
+ endif */
+ }
+
+ public String getTypeName()
+ {
+/* ifdef JDBC40 */
+ return "NCHAR";
+/* endif */
+/* ifndef JDBC40
+ return "CHAR";
+ endif */
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return value_.length();
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new HexReaderInputStream(new StringReader(getString()));
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return new AS400JDBCBlob(BinaryConverter.stringToBytes(getString()), maxLength_);
+ }
+ catch(NumberFormatException nfe)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ try
+ {
+ return BinaryConverter.stringToBytes(getString());
+ }
+ catch(NumberFormatException nfe)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+
+ public Object getObject()
+ throws SQLException
+ {
+ // This is written in terms of getString(), since it will
+ // handle truncating to the max field size if needed.
+ return getString();
+ }
+
+
+ public String getString()
+ throws SQLException
+ {
+ // Truncate to the max field size if needed.
+ // Do not signal a DataTruncation per the spec.
+ int maxFieldSize = settings_.getMaxFieldSize();
+ if((value_.length() > maxFieldSize) && (maxFieldSize > 0))
+ {
+ return value_.substring(0, maxFieldSize);
+ }
+ else
+ {
+ return value_;
+ }
+ }
+
+
+
+ // Added method trim() to trim the string.
+ public void trim()
+ {
+ value_ = value_.trim();
+ }
+
+
+
+
+ public String getNString() throws SQLException
+ {
+ // Truncate to the max field size if needed.
+ // Do not signal a DataTruncation per the spec.
+ int maxFieldSize = settings_.getMaxFieldSize();
+ if((value_.length() > maxFieldSize) && (maxFieldSize > 0))
+ {
+ return value_.substring(0, maxFieldSize);
+ }
+ else
+ {
+ return value_;
+ }
+ }
+
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+
+ //truncated_ = 0; outOfBounds_ = false;
+ //try
+ //{
+ // return new AS400JDBCRowId(BinaryConverter.stringToBytes(value_));
+ //}
+ //catch(NumberFormatException nfe)
+ //{
+ // this string contains non-hex characters
+ // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ // return null;
+ //}
+
+ //Decided this is of no use because rowid is so specific to the dbms internals.
+ //And there are issues in length and difficulties in converting to a
+ //valid rowid that is useful.
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public SQLXML getSQLXML() throws SQLException
+ {
+ //This is written in terms of getString(), since it will
+ // handle truncating to the max field size if needed.
+ truncated_ = 0; outOfBounds_ = false;
+ return new AS400JDBCSQLXML(getString());
+ }
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNClob.java b/jdbc40/com/ibm/as400/access/SQLNClob.java
new file mode 100644
index 000000000..2ffbfe4ff
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNClob.java
@@ -0,0 +1,570 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNClob.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+
+//@PDA jdbc40 brand new class
+//This is almost the same as SQLClob, and I would have liked to extend it, but it is final, and so decided
+//to not extend. It may come in handy for future NClob deviations also.
+
+final class SQLNClob extends SQLDataBase
+{
+
+ private int length_; // Length of string, in characters.
+ private int maxLength_; // Max length of field, in bytes.
+ private String value_;
+ private Object savedObject_; // This is our byte[] or InputStream or whatever that we save to convert to bytes until we really need to.
+
+ // Note: maxLength is in bytes not counting 2 for LL.
+ //
+ SQLNClob(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings);
+ length_ = 0;
+ maxLength_ = maxLength;
+ value_ = "";
+ }
+
+ public Object clone()
+ {
+ return new SQLNClob(maxLength_, settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ length_ = BinaryConverter.byteArrayToInt(rawBytes, offset);
+
+ int bidiStringType = settings_.getBidiStringType();
+
+ // if bidiStringType is not set by user, use ccsid to get value
+ if(bidiStringType == -1) bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ value_ = ccsidConverter.byteArrayToString(rawBytes, offset + 4, length_, bidiConversionProperties);
+ savedObject_ = null;
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+
+ try
+ {
+ int bidiStringType = settings_.getBidiStringType();
+ if(bidiStringType == -1) bidiStringType = ccsidConverter.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ byte[] temp = ccsidConverter.stringToByteArray(value_, bidiConversionProperties);
+ // The length in the first 4 bytes is actually the length in characters.
+ BinaryConverter.intToByteArray(temp.length, rawBytes, offset);
+ if(temp.length > maxLength_)
+ {
+ maxLength_ = temp.length;
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, "Change Descriptor");
+ }
+ System.arraycopy(temp, 0, rawBytes, offset+4, temp.length);
+ }
+ catch(Exception e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ // If it's a String we check for data truncation.
+ if(object instanceof String)
+ {
+ String s = (String)object;
+ truncated_ = (s.length() > maxLength_ ? s.length()-maxLength_ : 0);
+ outOfBounds_ = false;
+ }
+ //@PDD jdbc40 (JDUtilities.JDBCLevel_ >= 20 incorrect logic, but n/a now
+ else if(!(object instanceof Clob) && //@PDC NClob extends Clob
+ !(object instanceof InputStream) &&
+ !(object instanceof Reader) //@PDC jdbc40
+/* ifdef JDBC40 */
+ && !(object instanceof SQLXML)
+/* endif */
+ ) //@PDC jdbc40
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ savedObject_ = object;
+ if(scale != -1) length_ = scale;
+ }
+
+ private void doConversion()
+ throws SQLException
+ {
+ try
+ {
+ Object object = savedObject_;
+ if(savedObject_ instanceof String)
+ {
+ value_ = (String)object;
+ }
+ else if(object instanceof Reader)
+ {
+ if(length_ >= 0)
+ {
+ try
+ {
+ int blockSize = length_ < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length_ : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ Reader stream = (Reader)object;
+ StringBuffer buf = new StringBuffer();
+ char[] charBuffer = new char[blockSize];
+ int totalCharsRead = 0;
+ int charsRead = stream.read(charBuffer, 0, blockSize);
+ while(charsRead > -1 && totalCharsRead < length_)
+ {
+ buf.append(charBuffer, 0, charsRead);
+ totalCharsRead += charsRead;
+ int charsRemaining = length_ - totalCharsRead;
+ if(charsRemaining < blockSize)
+ {
+ blockSize = charsRemaining;
+ }
+ charsRead = stream.read(charBuffer, 0, blockSize);
+ }
+ value_ = buf.toString();
+
+ if(value_.length() < length_)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else if(length_ == -2) //@readerlen new else-if block (read all data)
+ {
+ try
+ {
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ Reader stream = (Reader)object;
+ StringBuffer buf = new StringBuffer();
+ char[] charBuffer = new char[blockSize];
+ int totalCharsRead = 0;
+ int charsRead = stream.read(charBuffer, 0, blockSize);
+ while(charsRead > -1 )
+ {
+ buf.append(charBuffer, 0, charsRead);
+ totalCharsRead += charsRead;
+
+ charsRead = stream.read(charBuffer, 0, blockSize);
+ }
+ value_ = buf.toString();
+
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ else if( object instanceof Clob) //@PDC jdbc40 - NClob isa Clob
+ {
+ Clob clob = (Clob)object;
+ value_ = clob.getSubString(1, (int)clob.length());
+ }
+/* ifdef JDBC40 */
+ else if( object instanceof SQLXML ) //@PDA jdbc40
+ {
+ SQLXML xml = (SQLXML)object;
+ value_ = xml.getString();
+ }
+/* endif */
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ // Truncate if necessary.
+ int valueLength = value_.length();
+ if(valueLength > maxLength_)
+ {
+ value_ = value_.substring(0, maxLength_);
+ truncated_ = valueLength - maxLength_;
+ outOfBounds_ = false;
+ }
+ else
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ }
+
+ length_ = value_.length();
+ }
+ finally
+ {
+ savedObject_ = null;
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NCLOB;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ return maxLength_;
+ }
+
+ public String getJavaClassName()
+ {
+ return "com.ibm.as400.access.AS400JDBCNClob";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "NCLOB";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return AS400JDBCDatabaseMetaData.MAX_LOB_LENGTH; //@xml3 // the DB2 SQL reference says this should be 2147483647 but we return 1 less to allow for NOT NULL columns
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 408;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+/* ifdef JDBC40 */
+ return java.sql.Types.NCLOB;
+/* endif */
+/* ifndef JDBC40
+ return java.sql.Types.CLOB;
+ endif */
+
+
+ }
+
+ public String getTypeName()
+ {
+ return "NCLOB";
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return value_.length();
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ return new HexReaderInputStream(new StringReader(value_));
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return new AS400JDBCBlob(BinaryConverter.stringToBytes(value_), maxLength_);
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this NClob contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return false;
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return BinaryConverter.stringToBytes(value_);
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this NClob contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+/* ifdef JDBC40 */
+ return new AS400JDBCNClob(value_, maxLength_);
+/* endif */
+/* ifndef JDBC40
+ return new AS400JDBCClob(value_, maxLength_);
+ endif */
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public String getNString() throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+ //
+ //if(savedObject_ != null) doConversion();
+ //truncated_ = 0; outOfBounds_ = false;
+ //try
+ //{
+ // return new AS400JDBCRowId(BinaryConverter.stringToBytes(value_));
+ //}
+ //catch(NumberFormatException nfe)
+ //{
+ // this NClob contains non-hex characters
+ //JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ //return null;
+ //}
+
+ //Decided this is of no use because rowid is so specific to the dbms internals.
+ //And there are issues in length and difficulties in converting to a
+ //valid rowid that is useful.
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public SQLXML getSQLXML() throws SQLException
+ {
+ if(savedObject_ != null) doConversion();
+ truncated_ = 0; outOfBounds_ = false;
+ return new AS400JDBCSQLXML(value_);
+ }
+
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNClobLocator.java b/jdbc40/com/ibm/as400/access/SQLNClobLocator.java
new file mode 100644
index 000000000..bf872fa4f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNClobLocator.java
@@ -0,0 +1,1020 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNclobLocator.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+//@PDA jdbc40 new class
+
+final class SQLNClobLocator implements SQLLocator
+{
+
+ private AS400JDBCConnection connection_;
+ private SQLConversionSettings settings_;
+ private ConvTable converter_;
+ private int id_;
+ private JDLobLocator locator_;
+ private int maxLength_;
+ private int truncated_;
+ private boolean outOfBounds_;
+ private int columnIndex_;
+ private String value_; //@loch //Note that value_ is not used as the output for a ResultSet.getX() call. We Get the value from a call to the JDLocator (not from value_) and not from the savedObject_, unless resultSet.updateX(obj1) is called followed by a obj2 = resultSet.getX()
+
+ private Object savedObject_; // This is the AS400JDBCBlobLocator or InputStream or whatever got set into us.
+ private int scale_; // This is actually the length that got set into us.
+
+ SQLNClobLocator(AS400JDBCConnection connection,
+ int id,
+ int maxLength,
+ SQLConversionSettings settings,
+ ConvTable converter,
+ int columnIndex)
+ {
+ connection_ = connection;
+ id_ = id;
+ locator_ = new JDLobLocator(connection, id, maxLength, false);
+ maxLength_ = maxLength;
+ truncated_ = 0; outOfBounds_ = false;
+ settings_ = settings;
+ converter_ = converter;
+ columnIndex_ = columnIndex;
+ }
+
+ public Object clone()
+ {
+ return new SQLNClobLocator(connection_, id_, maxLength_, settings_, converter_, columnIndex_);
+ }
+
+ public void setHandle(int handle)
+ {
+ locator_.setHandle(handle);
+ }
+
+ //@loch
+ public int getHandle()
+ {
+ return locator_.getHandle();
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ int locatorHandle = BinaryConverter.byteArrayToInt(rawBytes, offset);
+ locator_.setHandle(locatorHandle);
+ locator_.setColumnIndex(columnIndex_);
+ }
+
+ // This is only called from AS400JDBCPreparedStatement in one place.
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException
+ {
+ BinaryConverter.intToByteArray(locator_.getHandle(), rawBytes, offset);
+
+ // Now we write our saved data to the system, because the prepared statement is being executed.
+ // We used to write the data to the system on the call to set(), but this messed up
+ // batch executes, since the host server only reserves temporary space for locator handles one row at a time.
+ // See the toObject() method in this class for more details.
+ if(savedObject_ != null) writeToServer();
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ //@selins1
+ // If it's a String we check for data truncation.
+ if(object instanceof String)
+ {
+ String s = (String)object;
+ truncated_ = (s.length() > maxLength_ ? s.length()-maxLength_ : 0);
+ outOfBounds_ = false;
+ }
+ //@PDD jdbc40 (JDUtilities.JDBCLevel_ >= 20 incorrect logic, but n/a now
+ else if( !(object instanceof Reader) &&
+ !(object instanceof InputStream) &&
+ !(object instanceof Clob)
+/* ifdef JDBC40 */
+ && !(object instanceof SQLXML)
+/* endif */
+
+ ) //@PDC jdbc40
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ savedObject_ = object;
+ if(scale != -1) scale_ = scale; // Skip resetting it if we don't know the real length
+ }
+
+ //@loch method to temporary convert from object input to output before even going to host (writeToServer() does the conversion needed before writting to host)
+ //This will only be used when resultSet.updateX(obj1) is called followed by a obj2 = resultSet.getX()
+ //Purpose is to do a local type conversion from obj1 to obj2 like other non-locator lob types
+ private void doConversion()
+ throws SQLException
+ {
+ int length_ = scale_;
+
+ if( length_ == -1)
+ {
+ try{
+ //try to get length from locator
+ length_ = (int)locator_.getLength();
+ }catch(Exception e){ }
+ }
+
+ try
+ {
+ Object object = savedObject_;
+ if(savedObject_ instanceof String)
+ {
+ value_ = (String)object;
+ }
+ else if(object instanceof Reader)
+ {
+ if(length_ >= 0)
+ {
+ try
+ {
+ int blockSize = length_ < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length_ : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ Reader stream = (Reader)object;
+ StringBuffer buf = new StringBuffer();
+ char[] charBuffer = new char[blockSize];
+ int totalCharsRead = 0;
+ int charsRead = stream.read(charBuffer, 0, blockSize);
+ while(charsRead > -1 && totalCharsRead < length_)
+ {
+ buf.append(charBuffer, 0, charsRead);
+ totalCharsRead += charsRead;
+ int charsRemaining = length_ - totalCharsRead;
+ if(charsRemaining < blockSize)
+ {
+ blockSize = charsRemaining;
+ }
+ charsRead = stream.read(charBuffer, 0, blockSize);
+ }
+ value_ = buf.toString();
+
+ if(value_.length() < length_)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else if(length_ == -2) //@readerlen new else-if block (read all data)
+ {
+ try
+ {
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ Reader stream = (Reader)object;
+ StringBuffer buf = new StringBuffer();
+ char[] charBuffer = new char[blockSize];
+ int totalCharsRead = 0;
+ int charsRead = stream.read(charBuffer, 0, blockSize);
+ while(charsRead > -1)
+ {
+ buf.append(charBuffer, 0, charsRead);
+ totalCharsRead += charsRead;
+
+ charsRead = stream.read(charBuffer, 0, blockSize);
+ }
+ value_ = buf.toString();
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ else if( object instanceof Clob)
+ {
+ Clob clob = (Clob)object;
+ value_ = clob.getSubString(1, (int)clob.length());
+ }
+/* ifdef JDBC40 */
+ else if( object instanceof SQLXML )
+ {
+ SQLXML xml = (SQLXML)object;
+ value_ = xml.getString();
+ }
+/* endif */
+
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ // Truncate if necessary.
+ int valueLength = value_.length();
+ if(valueLength > maxLength_)
+ {
+ value_ = value_.substring(0, maxLength_);
+ }
+ }
+ finally
+ {
+ //nothing
+ }
+ }
+
+ private void writeToServer()
+ throws SQLException
+ {
+ try
+ {
+ Object object = savedObject_;
+ if(object instanceof String)
+ {
+ String string = (String)object;
+ int bidiStringType = settings_.getBidiStringType();
+ if(bidiStringType == -1) bidiStringType = converter_.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ byte[] bytes = converter_.stringToByteArray(string, bidiConversionProperties);
+ locator_.writeData(0L, bytes, true);
+ }
+ else if(object instanceof Reader)
+ {
+ int length = scale_; // hack to get the length into the set method
+ // Need to write even if there are 0 bytes in case we are batching and
+ // the host server reuses the same handle for the previous locator; otherwise,
+ // we'll have data in the current row from the previous row.
+ if (length == 0)
+ {
+ locator_.writeData(0, new byte[0], 0, 0, true);
+ }
+ else if(length > 0)
+ {
+ try
+ {
+ int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ int bidiStringType = settings_.getBidiStringType();
+ if(bidiStringType == -1) bidiStringType = converter_.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ ReaderInputStream stream = new ReaderInputStream((Reader)savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize);
+ try{
+ byte[] byteBuffer = new byte[blockSize];
+
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 && totalBytesRead < length)
+ {
+ locator_.writeData((long)totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset.
+ totalBytesRead += bytesRead;
+ int bytesRemaining = length - totalBytesRead;
+ if(bytesRemaining < blockSize)
+ {
+ blockSize = bytesRemaining;
+ if(stream.available() == 0 && blockSize != 0)
+ {
+ stream = new ReaderInputStream((Reader)savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize); // do this so we don't read more chars out of the Reader than we have to. //@KBC changed to use bidiConversionProperties instead of bidiStringType
+ }
+ }
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+
+
+ if(totalBytesRead < length)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }finally{
+ try{
+ stream.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "writeToServer stream.close()", e);
+ }
+ }
+
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else if(length == -2) //@readerlen new else-if block (read all data)
+ {
+ try
+ {
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ int bidiStringType = settings_.getBidiStringType();
+ if(bidiStringType == -1) bidiStringType = converter_.bidiStringType_;
+
+ BidiConversionProperties bidiConversionProperties = new BidiConversionProperties(bidiStringType);
+ bidiConversionProperties.setBidiImplicitReordering(settings_.getBidiImplicitReordering());
+ bidiConversionProperties.setBidiNumericOrderingRoundTrip(settings_.getBidiNumericOrdering());
+
+ ReaderInputStream stream = new ReaderInputStream((Reader)savedObject_, converter_.getCcsid(), bidiConversionProperties, blockSize);
+ try{
+ byte[] byteBuffer = new byte[blockSize];
+
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 )
+ {
+ locator_.writeData((long)totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset.
+ totalBytesRead += bytesRead;
+
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+
+ }finally{
+ try{
+ stream.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "writeToServer stream2.close()", e);
+ }
+ }
+
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ else if(object instanceof InputStream)
+ {
+ int length = scale_; // hack to get the length into the set method
+ // Need to write even if there are 0 bytes in case we are batching and
+ // the host server reuses the same handle for the previous locator; otherwise,
+ // we'll have data in the current row from the previous row.
+ if (length == 0)
+ {
+ locator_.writeData(0, new byte[0], 0, 0, true);
+ }
+ else if(length > 0)
+ {
+ InputStream stream = (InputStream)savedObject_;
+ int blockSize = length < AS400JDBCPreparedStatement.LOB_BLOCK_SIZE ? length : AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ byte[] byteBuffer = new byte[blockSize];
+ try
+ {
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 && totalBytesRead < length)
+ {
+ locator_.writeData((long)totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset.
+ totalBytesRead += bytesRead;
+ int bytesRemaining = length - totalBytesRead;
+ if(bytesRemaining < blockSize)
+ {
+ blockSize = bytesRemaining;
+ }
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+
+ if(totalBytesRead < length)
+ {
+ // a length longer than the stream was specified
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else if(length == -2) //@readerlen new else-if block (read all data)
+ {
+ InputStream stream = (InputStream)savedObject_;
+ int blockSize = AS400JDBCPreparedStatement.LOB_BLOCK_SIZE;
+ byte[] byteBuffer = new byte[blockSize];
+ try
+ {
+ int totalBytesRead = 0;
+ int bytesRead = stream.read(byteBuffer, 0, blockSize);
+ while(bytesRead > -1 )
+ {
+ locator_.writeData((long)totalBytesRead, byteBuffer, 0, bytesRead, true); // totalBytesRead is our offset.
+ totalBytesRead += bytesRead;
+
+ bytesRead = stream.read(byteBuffer, 0, blockSize);
+ }
+
+ }
+ catch(IOException ie)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, ie);
+ }
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ else if( object instanceof Clob) //check for jdbc level to know if lobs exist //@PDD jdbc40 NClob isa Clob
+ {
+ // Start new code for updateable locator case
+ boolean set = false;
+ if(object instanceof AS400JDBCClobLocator) //@PDA jdbc40 comment: AS400JDBCNClobLocator isa AS400JDBCClobLocator
+ {
+ AS400JDBCClobLocator clob = (AS400JDBCClobLocator)object;
+
+ //Synchronize on a lock so that the user can't keep making updates
+ //to the clob while we are taking updates off the vectors.
+ synchronized(clob)
+ {
+ // See if we saved off our real object from earlier.
+ if(clob.savedObject_ != null)
+ {
+ savedObject_ = clob.savedObject_;
+ scale_ = clob.savedScale_;
+ clob.savedObject_ = null;
+ writeToServer();
+ return;
+ }
+ }
+ }
+
+ //If the code for updateable lob locators did not run, then run old code.
+ if(!set)
+ {
+ Clob clob = (Clob)object;
+ int length = (int)clob.length();
+ String substring = clob.getSubString(1, length);
+ // @J5C Use length of output array not substring
+ byte[] outByteArray = converter_.stringToByteArray(substring);
+ locator_.writeData(0L, outByteArray, 0, outByteArray.length, true);
+ set = true;
+ }
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+/* ifdef JDBC40 */
+ else if( object instanceof SQLXML ) //@PDA jdbc40
+ {
+ SQLXML xml = (SQLXML)object;
+
+ String stringVal = xml.getString();
+ // @J5C Use length of output array not substring
+ byte[] outByteArray = converter_.stringToByteArray(stringVal);
+ locator_.writeData(0L, outByteArray, 0, outByteArray.length, true);
+ }
+/* endif */
+ else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+ finally
+ {
+ savedObject_ = null;
+ }
+ scale_ = (int)locator_.getLength();
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NCLOB_LOCATOR;
+ }
+
+ public String getCreateParameters()
+ {
+ return AS400JDBCDriver.getResource("MAXLENGTH");
+ }
+
+ public int getDisplaySize()
+ {
+ return maxLength_;
+ }
+
+ public String getJavaClassName()
+ {
+ return "com.ibm.as400.access.AS400JDBCNClobLocator";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "NCLOB";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return AS400JDBCDatabaseMetaData.MAX_LOB_LENGTH; //@xml3 // the DB2 SQL reference says this should be 2147483647 but we return 1 less to allow for NOT NULL columns
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 964;
+ }
+
+ public int getPrecision()
+ {
+ return maxLength_;
+ }
+
+ public int getRadix()
+ {
+ return 0;
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+/* ifdef JDBC40 */
+ return java.sql.Types.NCLOB;
+/* endif */
+/* ifndef JDBC40
+ return java.sql.Types.CLOB;
+ endif */
+ }
+
+ public String getTypeName()
+ {
+/* ifdef JDBC40 */
+ return "NCLOB";
+/* endif */
+/* ifndef JDBC40
+ return "CLOB";
+ endif */
+ }
+
+ public boolean isSigned()
+ {
+ return false;
+ }
+
+ public boolean isText()
+ {
+ return true;
+ }
+
+ public int getActualSize()
+ {
+ return maxLength_;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+ public InputStream getAsciiStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new ByteArrayInputStream(ConvTable.getTable(819, null).stringToByteArray(value_));//@loch
+ } //@loch
+
+ return new ReaderInputStream(new ConvTableReader(new AS400JDBCInputStream(new JDLobLocator(locator_)), converter_.getCcsid()), 819); // ISO-8859-1.
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new HexReaderInputStream(new StringReader(value_)); //@loch
+ } //@loch
+
+ return new HexReaderInputStream(new ConvTableReader(new AS400JDBCInputStream(new JDLobLocator(locator_)), converter_.getCcsid()));
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ byte[] bytes = BinaryConverter.stringToBytes(getString());
+ return new AS400JDBCBlob(bytes, bytes.length);
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this Clob contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return false;
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ return BinaryConverter.stringToBytes(getString());
+ }
+ catch(NumberFormatException nfe)
+ {
+ // this Clob contains non-hex characters
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ return null;
+ }
+ }
+
+ public Reader getCharacterStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new StringReader(value_); //@loch
+ } //@loch
+
+ return new ConvTableReader(new AS400JDBCInputStream(new JDLobLocator(locator_)), converter_.getCcsid());
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+ public Clob getClob()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new AS400JDBCClob(value_, maxLength_); //@loch
+ } //@loch
+
+ return new AS400JDBCClobLocator(new JDLobLocator(locator_), converter_, savedObject_, scale_);
+ }
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // getObject is used by AS400JDBCPreparedStatement for batching, so we save off our InputStream
+ // inside the AS400JDBCNClobLocator. Then, when convertToRawBytes() is called, the writeToServer()
+ // code checks the AS400JDBCNClobLocator's saved InputStream... if it exists, then it writes the
+ // data out of the InputStream to the system by calling writeToServer() again.
+/* ifdef JDBC40 */
+ return new AS400JDBCNClobLocator(new JDLobLocator(locator_), converter_, savedObject_, scale_);
+/* endif */
+/* ifndef JDBC40
+ return new AS400JDBCClobLocator(new JDLobLocator(locator_), converter_, savedObject_, scale_);
+
+ endif */
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return 0;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return value_; //@loch
+ } //@loch
+
+ DBLobData data = locator_.retrieveData(0, locator_.getMaxLength());
+ String value = converter_.byteArrayToString(data.getRawBytes(),
+ data.getOffset(),
+ data.getLength());
+ truncated_ = 0; outOfBounds_ = false; //@pda jdbc40 make consistent with other SQLData Clob classes
+ return value;
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public InputStream getUnicodeStream()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ try
+ {
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new ReaderInputStream(new StringReader(value_), 13488); //@loch
+ } //@loch
+
+
+ return new ReaderInputStream(new ConvTableReader(new AS400JDBCInputStream(new JDLobLocator(locator_)), converter_.getCcsid()), 13488);
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+
+ public Reader getNCharacterStream() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new StringReader(value_); //@loch
+ } //@loch
+
+ try
+ {
+ return new ConvTableReader(new AS400JDBCInputStream(new JDLobLocator(locator_)), converter_.getCcsid());
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, e);
+ return null;
+ }
+ }
+
+/* ifdef JDBC40 */
+ public NClob getNClob() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new AS400JDBCNClob(value_, maxLength_); //@loch
+ } //@loch
+
+ return new AS400JDBCNClobLocator(new JDLobLocator(locator_), converter_, savedObject_, scale_);
+
+ }
+/* endif */
+
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return value_; //@loch
+ } //@loch
+
+ DBLobData data = locator_.retrieveData(0, locator_.getMaxLength());
+ String value = converter_.byteArrayToString(data.getRawBytes(),
+ data.getOffset(),
+ data.getLength());
+ return value;
+ }
+
+/* ifdef JDBC40 */
+ public RowId getRowId() throws SQLException
+ {
+
+ //truncated_ = 0; outOfBounds_ = false;
+ //try
+ //{
+ // return new AS400JDBCRowId(BinaryConverter.stringToBytes(getString()));
+ //}
+ //catch(NumberFormatException nfe)
+ //{
+ // this Clob contains non-hex characters
+ // JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe);
+ // return null;
+ //}
+
+ //Decided this is of no use because rowid is so specific to the dbms internals.
+ //And there are issues in length and difficulties in converting to a
+ //valid rowid that is useful.
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public SQLXML getSQLXML() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(savedObject_ != null)//@loch
+ { //@loch
+ //get value from RS.updateX(value)
+ doConversion(); //@loch
+ truncated_ = 0; outOfBounds_ = false; //@loch
+ return new AS400JDBCSQLXML(value_, maxLength_); //@loch
+ } //@loch
+ return new AS400JDBCSQLXML( getString() );
+ }
+/* endif */
+
+ // @array
+ public Array getArray() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public void updateSettings(SQLConversionSettings settings) {
+ settings_ = settings;
+ }
+
+}
+
+
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNVarchar.java b/jdbc40/com/ibm/as400/access/SQLNVarchar.java
new file mode 100644
index 000000000..b4f6a85ec
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNVarchar.java
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNVarchar.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+
+//@PDA jdbc40 new class
+
+final class SQLNVarchar
+extends SQLVarcharBase
+{
+
+ // Note: maxLength is in bytes not counting 2 for LL.
+ //
+ SQLNVarchar(int maxLength, SQLConversionSettings settings)
+ {
+ super(settings, 0, maxLength, "");
+ }
+
+ public Object clone()
+ {
+ return new SQLNVarchar(maxLength_, settings_);
+ }
+
+
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NVARCHAR;
+ }
+
+
+ public String getLocalName()
+ {
+ return "NVARCHAR";
+ }
+
+ public int getType()
+ {
+/* ifdef JDBC40 */
+ return java.sql.Types.NVARCHAR;
+/* endif */
+/* ifndef JDBC40
+ return java.sql.Types.VARCHAR;
+ endif */
+ }
+
+ public String getTypeName()
+ {
+/* ifdef JDBC40 */
+ return "NVARCHAR";
+/* endif */
+
+/* ifndef JDBC40
+ return "VARCHAR";
+ endif */
+ }
+
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNumeric.java b/jdbc40/com/ibm/as400/access/SQLNumeric.java
new file mode 100644
index 000000000..cbd578de4
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNumeric.java
@@ -0,0 +1,528 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNumeric.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLNumeric
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private static final BigDecimal default_ = BigDecimal.valueOf(0); // @C2A
+ private static final BigDecimal BYTE_MAX_VALUE = BigDecimal.valueOf(Byte.MAX_VALUE);
+ private static final BigDecimal BYTE_MIN_VALUE = BigDecimal.valueOf(Byte.MIN_VALUE);
+ private static final BigDecimal SHORT_MAX_VALUE = BigDecimal.valueOf(Short.MAX_VALUE);
+ private static final BigDecimal SHORT_MIN_VALUE = BigDecimal.valueOf(Short.MIN_VALUE);
+ private static final BigDecimal INTEGER_MAX_VALUE = BigDecimal.valueOf(Integer.MAX_VALUE);
+ private static final BigDecimal INTEGER_MIN_VALUE = BigDecimal.valueOf(Integer.MIN_VALUE);
+ private static final BigDecimal LONG_MAX_VALUE = BigDecimal.valueOf(Long.MAX_VALUE);
+ private static final BigDecimal LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
+ static final BigDecimal FLOAT_MAX_VALUE = new BigDecimal(Float.MAX_VALUE);
+ static final BigDecimal FLOAT_MIN_VALUE = new BigDecimal(Float.MIN_VALUE);
+ static final BigDecimal DOUBLE_MAX_VALUE = new BigDecimal(Double.MAX_VALUE);
+ static final BigDecimal DOUBLE_MIN_VALUE = new BigDecimal(Double.MIN_VALUE);
+
+ private int precision_;
+ private int scale_;
+ private AS400ZonedDecimal typeConverter_;
+ private BigDecimal value_;
+ private JDProperties properties_; // @M0A - added JDProperties so we can get the scale & precision
+ private int vrm_; // @M0A
+
+ SQLNumeric(int precision,
+ int scale,
+ SQLConversionSettings settings,
+ int vrm, // @M0C
+ JDProperties properties) // @M0C
+ {
+ super(settings);
+ precision_ = precision;
+ scale_ = scale;
+ typeConverter_ = new AS400ZonedDecimal(precision_, scale_);
+ value_ = default_; // @C2C
+ vrm_ = vrm; // @M0A
+ properties_ = properties; // @M0A
+ }
+
+ public Object clone()
+ {
+ return new SQLNumeric(precision_, scale_, settings_, vrm_, properties_); // @M0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = ((BigDecimal)typeConverter_.toObject(rawBytes, offset));
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ try{
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ }
+ catch(ExtendedIllegalArgumentException e){
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, e);
+ }
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ BigDecimal bigDecimal = null;
+
+ if(object instanceof String) {
+ try
+ {
+ String value = SQLDataFactory.convertScientificNotation((String)object, settings_); // @F3C
+ if(scale >= 0)
+ value = SQLDataFactory.truncateScale(value, scale);
+ bigDecimal = new BigDecimal(value);
+ }
+ catch(NumberFormatException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return;
+ }
+ catch(StringIndexOutOfBoundsException e) // jdk 1.3.x throws this instead of a NFE
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return;
+ }
+ } else if(object instanceof Number) {
+ String value = SQLDataFactory.convertScientificNotation(object.toString(), settings_); // @C1C
+ if(scale >= 0)
+ value = SQLDataFactory.truncateScale(value, scale);
+ bigDecimal = new BigDecimal(value);
+ } else if(object instanceof Boolean) {
+ bigDecimal = (((Boolean)object).booleanValue() == true) ? BigDecimal.valueOf(1) : BigDecimal.valueOf(0);
+
+ } else {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return;
+ }
+
+ // Truncate if necessary. If we ONLY truncate on the right side, we don't @E3C
+ // need to report it. If we truncate on the left side, then we report the @E3A
+ // number of truncated digits on both ends...this will make the dataSize @E3A
+ // and transferSize make sense on the resulting DataTruncation. @E3A
+ truncated_ = 0; outOfBounds_ = false;
+ int otherScale = bigDecimal.scale();
+ if(otherScale > scale_)
+ truncated_ += otherScale - scale_;
+ value_ = bigDecimal.setScale(scale_, BigDecimal.ROUND_DOWN); // @E3C
+
+ int otherPrecision = SQLDataFactory.getDecimalPrecision(value_); /*@H5A*/
+ // Check for the odd case where the precision = scale and adjust the otherPrecision @H5C
+ if (precision_ == scale_) {
+ if (value_.intValue() == 0) {
+ otherPrecision = otherPrecision - 1;
+ }
+ }
+ if(otherPrecision > precision_)
+ { // @E2D @E3C
+ int digits = otherPrecision - precision_; // @E2D @E3C
+ truncated_ += digits; // @E2D @E3C
+ value_ = SQLDataFactory.truncatePrecision(value_, digits); // @E2D @E3C
+ } // @E2D @E3C
+ else // @E3A
+ truncated_ = 0; outOfBounds_ = false; // No left side truncation, report nothing @E3A
+ // (even if there was right side truncation). @E3A
+
+ /* @E3D
+ int otherLeftSide = otherPrecision - otherScale; // @E2A
+ int leftSide = precision_ - scale_; // @E2A
+ if(otherLeftSide > leftSide) { // @E2A
+ int digits = otherLeftSide - leftSide; // @E2A
+ truncated_ += digits; // @E2A
+ value_ = SQLDataFactory.truncatePrecision(value_, digits + scale_); // @E2A
+ } // @E2A
+ */
+
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NUMERIC;
+ }
+
+ public String getCreateParameters()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(AS400JDBCDriver.getResource("PRECISION"));
+ buffer.append(",");
+ buffer.append(AS400JDBCDriver.getResource("SCALE"));
+ return buffer.toString();
+ }
+
+ public int getDisplaySize()
+ {
+ return precision_ + 2;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "NUMERIC";
+ }
+
+ public int getMaximumPrecision()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ else
+ return 31;
+ }
+
+ public int getMaximumScale()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ else
+ return 31;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 488;
+ }
+
+ public int getPrecision()
+ {
+ return precision_;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return scale_;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.NUMERIC;
+ }
+
+ public String getTypeName()
+ {
+ return "NUMERIC";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return precision_;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(scale >= 0)
+ {
+ if(scale >= value_.scale())
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_.setScale(scale);
+ }
+ else
+ {
+ truncated_ = value_.scale() - scale;
+ return value_.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return value_;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_.compareTo(BigDecimal.valueOf(0)) != 0);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(BYTE_MAX_VALUE) > 0 || value_.compareTo(BYTE_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 1;
+ outOfBounds_ = true;
+ }
+ return(byte) value_.byteValue();
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ double d = value_.doubleValue(); //@KBA
+ //@KBD This will never be the case with the current precision
+ //@KBD if(value_.compareTo(DOUBLE_MAX_VALUE) > 0 || value_.compareTo(DOUBLE_MIN_VALUE) < 0)
+ if( d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY) //@KBA
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 8;
+ outOfBounds_ = true;
+ }
+ return d; //@KBC value_.doubleValue();
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ float f = value_.floatValue(); //@KBA
+ //@KBD Changed to avoid optimization problem with JRE 1.3
+ //@KBD if(value_.compareTo(FLOAT_MAX_VALUE) > 0 || value_.compareTo(FLOAT_MIN_VALUE) < 0)
+ if(f == Float.POSITIVE_INFINITY || f == Float.NEGATIVE_INFINITY) //@KBA
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 4;
+ outOfBounds_ = true;
+ }
+ return f; //@KBC value_.floatValue();
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(INTEGER_MAX_VALUE) > 0 || value_.compareTo(INTEGER_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 4;
+ outOfBounds_ = true;
+ }
+ return value_.intValue();
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(LONG_MAX_VALUE) > 0 || value_.compareTo(LONG_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 8;
+ outOfBounds_ = true;
+ }
+ return value_.longValue();
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_.compareTo(SHORT_MAX_VALUE) > 0 || value_.compareTo(SHORT_MIN_VALUE) < 0)
+ {
+ // we don't count the fractional part of the number as truncation
+ int length = value_.toBigInteger().toByteArray().length;
+ truncated_ = length - 2;
+ outOfBounds_ = true;
+ }
+ return(short) value_.shortValue();
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = JDUtilities.bigDecimalToPlainString(value_); //@big java 1.5 support
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = value_.toString();
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+/* endif */
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLNumeric2.java b/jdbc40/com/ibm/as400/access/SQLNumeric2.java
new file mode 100644
index 000000000..6047e6a7d
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLNumeric2.java
@@ -0,0 +1,434 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLNumeric2.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Blob;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+// This uses a double instead of a BigDecimal (like SQLNumeric does).
+// It will be faster but won't really preserve a lot of normal
+// JDBC semantics. This will be documented in the "big decimal"
+// property.
+//
+final class SQLNumeric2
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private int precision_;
+ private int scale_;
+ private AS400ZonedDecimal typeConverter_;
+ private double value_;
+ private JDProperties properties_; // @M0A - added JDProperties so we can get the scale & precision
+ private int vrm_; // @M0A
+
+ SQLNumeric2(int precision,
+ int scale,
+ SQLConversionSettings settings,
+ int vrm, // @M0C
+ JDProperties properties) // @M0C
+ {
+ super(settings);
+ precision_ = precision;
+ scale_ = scale;
+ typeConverter_ = new AS400ZonedDecimal(precision_, scale_);
+ value_ = 0;
+ vrm_ = vrm; // @M0A
+ properties_ = properties; // @M0A
+ }
+
+ public Object clone()
+ {
+ return new SQLNumeric2(precision_, scale_, settings_, vrm_, properties_); // @M0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = typeConverter_.toDouble(rawBytes, offset);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ typeConverter_.toBytes(value_, rawBytes, offset);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ if(object instanceof String)
+ {
+ try
+ {
+ value_ = Double.valueOf((String)object).doubleValue();
+ }
+ catch(NumberFormatException nfe)
+ { // @E4A
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH, nfe); // @E4A
+ }
+ }
+
+ else if(object instanceof Number)
+ value_ = ((Number)object).doubleValue();
+
+ else if(object instanceof Boolean)
+ value_ = ((Boolean)object).booleanValue() ? 1 : 0;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.NUMERIC_USING_DOUBLE;
+ }
+
+ public String getCreateParameters()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(AS400JDBCDriver.getResource("PRECISION"));
+ buffer.append(",");
+ buffer.append(AS400JDBCDriver.getResource("SCALE"));
+ return buffer.toString();
+ }
+
+ public int getDisplaySize()
+ {
+ return precision_ + 2;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.math.BigDecimal";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "NUMERIC";
+ }
+
+ public int getMaximumPrecision()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ else
+ return 31;
+ }
+
+ public int getMaximumScale()
+ {
+ // @M0C - change to check vrm and JDProperties
+ if(vrm_ >= JDUtilities.vrm530)
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ else
+ return 31;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 488;
+ }
+
+ public int getPrecision()
+ {
+ return precision_;
+ }
+
+ public int getRadix()
+ {
+ return 10;
+ }
+
+ public int getScale()
+ {
+ return scale_;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.NUMERIC;
+ }
+
+ public String getTypeName()
+ {
+ return "NUMERIC";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return precision_;
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new BigDecimal(value_);
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE)
+ {
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 7; outOfBounds_ = true;
+ }
+ else
+ {
+ truncated_ = 3; outOfBounds_ = true;
+ }
+ }
+ else
+ {
+ truncated_ = 1; outOfBounds_ = true;
+ }
+ }
+ return(byte) value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return value_;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Float.MAX_VALUE || value_ < -Float.MAX_VALUE) //@trunc min_val is a posative number. //Float.MIN_VALUE)
+ {
+ truncated_ = 4; outOfBounds_ = true;
+ }
+ return(float)value_;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 4; outOfBounds_ = true;
+ }
+ return(int)value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Long.MAX_VALUE || value_ < Long.MIN_VALUE)
+ {
+ truncated_ = 1; // this is not necessarily correct, but we know there is truncation
+ outOfBounds_ = true;
+ }
+ return(long)value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Double(value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)
+ {
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE)
+ {
+ truncated_ = 6;
+ outOfBounds_ = true;
+ }
+ else
+ {
+ truncated_ = 2;
+ outOfBounds_ = true;
+ }
+ }
+ return(short) value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Double.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+
+/* ifdef JDBC40 */
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/SQLReal.java b/jdbc40/com/ibm/as400/access/SQLReal.java
new file mode 100644
index 000000000..469eded60
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLReal.java
@@ -0,0 +1,495 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLReal.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-2001 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLReal
+extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private float value_;
+
+ SQLReal(SQLConversionSettings settings)
+ {
+ super(settings);
+ value_ = 0.0f;
+ }
+
+ public Object clone()
+ {
+ return new SQLReal(settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ value_ = BinaryConverter.byteArrayToFloat(rawBytes, offset); // @D0C
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter) //@P0C
+ throws SQLException
+ {
+ BinaryConverter.floatToByteArray(value_, rawBytes, offset); // @D0C
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // SET METHODS //
+ // //
+ //---------------------------------------------------------//
+
+ public void set(Object object, Calendar calendar, int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(object instanceof String)
+ {
+ if (settings_.getDecimalSeparator().equals(",")){
+ object = ((String) object).replace(',','.');
+ }
+ try
+ {
+ value_ = Float.valueOf((String) object).floatValue();
+ // @E2d int objectLength = ((String) object).length();
+ // @E2d int valueLength = Float.toString(value_).length();
+ // @E2d if(valueLength < objectLength)
+ // @E2d truncated_ = objectLength - valueLength;
+ }
+ catch(NumberFormatException e)
+ {
+
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+ }
+
+ // @D9d
+ // We do not start messing with floating point values trying
+ // to figure out if they truncate. The performance of this
+ // in the BigDecimal case below is probably slower then creating
+ // a table on the system.
+ //
+ //else if(object instanceof Double) {
+ // value_ = ((Double) object).floatValue();
+ // if(((Double) object).doubleValue() > value_)
+ // truncated_ = 8;
+ //}
+ //
+ // @D9d
+ //else if(object instanceof BigDecimal) {
+ // value_ = ((BigDecimal) object).floatValue();
+ // int objectLength = SQLDataFactory.getPrecision((BigDecimal) object);
+ // int valueLength = SQLDataFactory.getPrecision(new BigDecimal(value_));
+ // if(valueLength < objectLength)
+ // truncated_ = objectLength - valueLength;
+ //}
+
+ else if(object instanceof Number)
+ {
+ // Set the value to the right type.
+ value_ = ((Number) object).floatValue(); // @D9c
+
+ // Get the whole number portion of that value.
+ //long value = (long) value_; // @D9c //@bigdectrunc change to follow native driver
+
+ // Get the original value as a long. This is the
+ // largest precision we can test for for a truncation.
+ //long truncTest = ((Number) object).longValue(); // @D9c //@bigdectrunc
+
+ // If they are not equal, then we truncated significant
+ // data from the original value the user wanted us to insert.
+ //if(truncTest != value) // @D9c //@bigdectrunc
+ //truncated_ = 1; //@bigdectrunc
+ }
+
+
+ else if(object instanceof Boolean)
+ value_ = (((Boolean) object).booleanValue() == true) ? 1f : 0f;
+
+ else
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // DESCRIPTION OF SQL TYPE //
+ // //
+ //---------------------------------------------------------//
+
+ public int getSQLType()
+ {
+ return SQLData.REAL;
+ }
+
+ public String getCreateParameters()
+ {
+ return null;
+ }
+
+
+ public int getDisplaySize()
+ {
+ return 13;
+ }
+
+ //@F1A JDBC 3.0
+ public String getJavaClassName()
+ {
+ return "java.lang.Float";
+ }
+
+ public String getLiteralPrefix()
+ {
+ return null;
+ }
+
+ public String getLiteralSuffix()
+ {
+ return null;
+ }
+
+ public String getLocalName()
+ {
+ return "REAL";
+ }
+
+ public int getMaximumPrecision()
+ {
+ return 24;
+ }
+
+ public int getMaximumScale()
+ {
+ return 0;
+ }
+
+ public int getMinimumScale()
+ {
+ return 0;
+ }
+
+ public int getNativeType()
+ {
+ return 480;
+ }
+
+ public int getPrecision()
+ {
+ return 24;
+ }
+
+ public int getRadix()
+ {
+ return 2; //@K1C Changed from 10
+ }
+
+ public int getScale()
+ {
+ return 0;
+ }
+
+ public int getType()
+ {
+ return java.sql.Types.REAL;
+ }
+
+ public String getTypeName()
+ {
+ return "REAL";
+ }
+
+ public boolean isSigned()
+ {
+ return true;
+ }
+
+ public boolean isText()
+ {
+ return false;
+ }
+
+ public int getActualSize()
+ {
+ return SQLDataFactory.getPrecision(Float.toString(value_));
+ }
+
+ public int getTruncated()
+ {
+ return truncated_;
+ }
+ public boolean getOutOfBounds() {
+ return outOfBounds_;
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSIONS TO JAVA TYPES //
+ // //
+ //---------------------------------------------------------//
+
+
+ public BigDecimal getBigDecimal(int scale)
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ // Convert the value to a String before creating the
+ // BigDecimal. This will create the exact BigDecimal
+ // that we want. If you pass the value directly to
+ // BigDecimal, then the value is not exact, and the
+ // scale becomes bigger than expected.
+
+ // @A0A
+ // Modified the code to deal with numbers in scientific
+ // notations. The numbers that are in scientific notation
+ // are parsed to a base (the part before 'E') and an
+ // exponent (the part after 'E'). The base is then used
+ // to construct the BigDecimal object and then the exponent
+ // is used to shift the decimal point to its rightful place.
+
+ // BigDecimal bigDecimal = new BigDecimal(Float.toString(value_)) // @A0D
+
+ BigDecimal bigDecimal = null; // @A0A
+
+ String numString = Float.toString(value_); // @A0A
+ int eIndex = numString.indexOf("E"); // @A0A
+ if(eIndex == -1)
+ { // @A0A
+ bigDecimal = new BigDecimal(numString); // @A0A
+ } // @A0A
+ else
+ { // @A0A
+ String base = numString.substring(0, eIndex); // @A0A
+ int exponent = Integer.parseInt(numString.substring(eIndex+1)); // @A0A
+ bigDecimal = new BigDecimal(base); // @A0A
+ bigDecimal = bigDecimal.movePointRight(exponent); // @A0A
+ } // @A0A
+
+ if(scale >= 0)
+ {
+ if(scale >= bigDecimal.scale())
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return bigDecimal.setScale(scale);
+ }
+ else
+ {
+ truncated_ = bigDecimal.scale() - scale;
+ outOfBounds_ = false;
+ return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
+ }
+ }
+ else
+ return bigDecimal;
+ }
+
+ public InputStream getBinaryStream()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Blob getBlob()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public boolean getBoolean()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(value_ != 0.0f);
+ }
+
+ public byte getByte()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Byte.MAX_VALUE || value_ < Byte.MIN_VALUE) //@trunc
+ { //@trunc
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE)//@trunc
+ { //@trunc
+ truncated_ = 3; //@trunc
+ outOfBounds_ = true;
+ } //@trunc
+ else //@trunc
+ { //@trunc
+ truncated_ = 1; //@trunc
+ outOfBounds_ = true;
+ } //@trunc
+ } //@trunc
+ return(byte) value_;
+ }
+
+ public byte[] getBytes()
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ public Date getDate(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public double getDouble()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(double) value_;
+ }
+
+ public float getFloat()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return(float) value_;
+ }
+
+ public int getInt()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+
+ if(value_ > Integer.MAX_VALUE || value_ < Integer.MIN_VALUE) //@trunc
+ { //@trunc
+ truncated_ = 4; //@trunc
+ outOfBounds_ = true;
+ } //@trunc
+
+ return(int) value_;
+ }
+
+ public long getLong()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Long.MAX_VALUE || value_ < Long.MIN_VALUE) //@trunc
+ { //@trunc
+ truncated_ = 8; //@trunc
+ outOfBounds_ = true;
+ } //@trunc
+ return(long) value_;
+ }
+
+ public Object getObject()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ return new Float(value_);
+ }
+
+ public short getShort()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ if(value_ > Short.MAX_VALUE || value_ < Short.MIN_VALUE) //@trunc
+ { //@trunc
+ truncated_ = 2; //@trunc
+ outOfBounds_ = true;
+ } //@trunc
+ return(short) value_;
+ }
+
+ public String getString()
+ throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Float.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+ public Time getTime(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ public Timestamp getTimestamp(Calendar calendar)
+ throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+
+ //@pda jdbc40
+ public String getNString() throws SQLException
+ {
+ truncated_ = 0; outOfBounds_ = false;
+ String stringRep = Float.toString(value_);
+ int decimal = stringRep.indexOf('.');
+ if(decimal == -1)
+ return stringRep;
+ else
+ return stringRep.substring(0, decimal)
+ + settings_.getDecimalSeparator()
+ + stringRep.substring(decimal+1);
+ }
+
+/* ifdef JDBC40 */
+
+ //@pda jdbc40
+ public RowId getRowId() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML() throws SQLException
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+/* endif */
+
+}
diff --git a/jdbc40/com/ibm/as400/access/SQLRowID.java b/jdbc40/com/ibm/as400/access/SQLRowID.java
new file mode 100644
index 000000000..06567337a
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/SQLRowID.java
@@ -0,0 +1,612 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: SQLRowID.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+final class SQLRowID extends SQLDataBase
+{
+ static final String copyright = "Copyright (C) 1997-2003 International Business Machines Corporation and others.";
+
+ // Private data.
+ private static final byte[] default_ = new byte[0];
+
+ private int length_;
+ private byte[] value_;
+
+ SQLRowID(SQLConversionSettings settings)
+ {
+ super(settings);
+ length_ = 0;
+ value_ = default_;
+ }
+
+ public Object clone()
+ {
+ return new SQLRowID(settings_);
+ }
+
+ //---------------------------------------------------------//
+ // //
+ // CONVERSION TO AND FROM RAW BYTES //
+ // //
+ //---------------------------------------------------------//
+
+ public void convertFromRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException {
+
+ length_ = BinaryConverter.byteArrayToUnsignedShort(rawBytes, offset);
+ value_ = new byte[length_];
+ System.arraycopy(rawBytes, offset+2, value_, 0, length_);
+ }
+
+ public void convertToRawBytes(byte[] rawBytes, int offset, ConvTable ccsidConverter)
+ throws SQLException {
+
+ BinaryConverter.unsignedShortToByteArray(length_, rawBytes, offset);
+ int len = (value_.length < rawBytes.length) ? value_.length : rawBytes.length;
+ System.arraycopy(value_, 0, rawBytes, offset + 2, len);
+ // pad rawBytes with zeros if it has room
+ for(int i=(offset + 2 + len); i
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.
+ * 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.
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ *
+ * 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.
+ *
+ * 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
+ *
+ * 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.
+
+ * 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
+ * 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; iClob
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 */
+
+
+/**
+
+
+ @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().
+
+
+
+ @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:
+ cursor hold
+ driver property.
+
+
+
+
+ @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.
+
+
+ String serverJobIdentifier = ((AS400JDBCConnection)connection).getServerJobIdentifier();
+
+
+ @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:
+
+ AS400 system = ((AS400JDBCConnection)connection).getSystem();
+
+
+
+ @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.
+
+
+
+ @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.
+
+
+
+ @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.
+
+
+
+ @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.
+
+
+
+ @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.
+ *
+ *
+ *
+ *
+ * @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.
+
+
+
+
+ @param level The transaction isolation level. Possible
+ values are:
+
+ IBM i isolation level JDBC transaction isolation level
+ *CHG TRANSACTION_READ_UNCOMMITTED
+ *CS TRANSACTION_READ_COMMITTED
+ *ALL TRANSACTION_READ_REPEATABLE_READ
+ *RR TRANSACTION_SERIALIZABLE
+
+
+ @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.
+
+ DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver
+ * and the maximum length that may be specified for each property.
+ * SQLException
. If the driver
+ * generates a SQLException
, the value specified was not set on the
+ * connection.
+ *
+ *
+ * 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.
+ * 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.
+ *
+ *
+ * DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver.
+ *
+ *
+ *
+ *
+ * Properties
object that contains the name and current value of
+ * each of the client info properties supported by the driver.
+ * 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:
+ *
+ *
+ * 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.
+ *
+ *
+*
+**/
+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().
+ *
+ *
+* // 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();
+*
+ *
+ * @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().
+
+
+
+ @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:
+ * cursor hold
+ driver property.
+ *
+ *
+ *
+ *
+ * @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.
+
+ * String serverJobIdentifier = ((AS400JDBCConnectionHandle)connection).getServerJobIdentifier();
+ *
+
+ @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:
+ *
+ AS400 system = ((AS400JDBCConnectionHandle)connection).getSystem();
+
+ *
+ *
+ * @exception SQLException If the connection is not open.
+ **/
+ public int getTransactionIsolation() throws SQLException
+ {
+ validateConnection();
+ return connection_.getTransactionIsolation();
+ }
+
+ /**
+ * Returns the type map.
+ *
+ *
+ *
+ * @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.
+
+
+
+ @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.
+ *
+ *
+
+@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.
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ * @param level The transaction isolation level. Possible values are:
+ *
+ * DB2 for IBM i isolation level JDBC transaction isolation level
+ * *CHG TRANSACTION_READ_UNCOMMITTED
+ * *CS TRANSACTION_READ_COMMITTED
+ * *ALL TRANSACTION_READ_REPEATABLE_READ
+ * *RR TRANSACTION_SERIALIZABLE
+ *
+ *
+ * @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.
+ *
+ * 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.
+ * 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.
+ *
+ *
+ * DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver.
+ *
+ *
+ *
+ *
+ * Properties
object that contains the name and current value of
+ * each of the client info properties supported by the driver.
+ * 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.
+ * DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver
+ * and the maximum length that may be specified for each property.
+ * SQLException
. If the driver
+ * generates a SQLException
, the value specified was not set on the
+ * connection.
+ *
+ *
+ *
+**/
+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.
+*
+*
+* // 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();
+*
+*
+*
+* // 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();
+*
+**/
+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.
+ *
+* // 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 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ *
+ *
+ * dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+ *
+ * @return The tracing level.
+ *
+ *
+ *
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ *
+ * 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ *
+ * 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:
+ *
+ *
+ * @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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ **/
+ 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+ *
+ * @param traceCategories level of tracing to start.
+ *
+ *
+ *
+ * dataSource.setServerTraceCategories(AS400JDBCDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+ *
+ * @param traceCategories level of tracing to start.
+ *
+ *
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ **/
+ 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
+ *
+ *
+ * The default value is "all" when connected to a server that supports compression of batched insert data and
+ * "true" when the server does not support compression of batched insert date
+ **/
+ /*@K3A*/
+ public void setVariableFieldCompression(String compress)
+ {
+ String property = "variableFieldCompression";
+
+ String oldValue = getVariableFieldCompression();
+
+ if ("true".equals(compress) ||
+ "false".equals(compress) ||
+ "insert".equals(compress) ||
+ "all".equals(compress) ) {
+
+ properties_.setString(JDProperties.VARIABLE_FIELD_COMPRESSION, compress);
+
+ changes_.firePropertyChange(property, oldValue, compress);
+
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation (this, property + ": " + compress);
+ }
+ }
+ }
+
+ // @F1A Added the below methods to set socket options
+ /**
+ * Gets the socket keepalive option.
+ * @return The value of the socket keepalive option.
+ **/
+ public boolean getKeepAlive()
+ {
+ return sockProps_.isKeepAlive();
+ }
+
+ /**
+ * Gets the socket receive buffer size option. NOTE: This does not get
+ * the actual receive buffer size, only the option which is used as a hint
+ * by the underlying socket code.
+ * @return The value of the socket receive buffer size option.
+ **/
+ public int getReceiveBufferSize()
+ {
+ return sockProps_.getReceiveBufferSize();
+ }
+
+ /**
+ * Gets the socket send buffer size option. NOTE: This does not get
+ * the actual send buffer size, only the option which is used as a hint
+ * by the underlying socket code.
+ * @return The value of the socket send buffer size option.
+ **/
+ public int getSendBufferSize()
+ {
+ return sockProps_.getSendBufferSize();
+ }
+
+ /**
+ * Gets the socket linger option in seconds.
+ * @return The value of the socket linger option.
+ **/
+ public int getSoLinger()
+ {
+ return sockProps_.getSoLinger();
+ }
+
+ /**
+ * Gets the socket timeout option in milliseconds.
+ * @return The value of the socket timeout option.
+ **/
+ public int getSoTimeout()
+ {
+ return sockProps_.getSoTimeout();
+ }
+
+ /**
+ * Gets the socket TCP no delay option.
+ * @return The value of the socket TCP no delay option.
+ **/
+ public boolean getTcpNoDelay()
+ {
+ return sockProps_.isTcpNoDelay();
+ }
+
+ /**
+ * This property allows the turning on of socket keep alive.
+ * @param keepAlive The keepalive option value.
+ **/
+ public void setKeepAlive(boolean keepAlive)
+ {
+ sockProps_.setKeepAlive(keepAlive);
+ }
+
+ /**
+ * This property sets the receive buffer size socket option to the
+ * specified value. The receive buffer size option is used as a hint
+ * for the size to set the underlying network I/O buffers. Increasing
+ * the receive buffer size can increase the performance of network
+ * I/O for high-volume connection, while decreasing it can help reduce
+ * the backlog of incoming data. This value must be greater than 0.
+ * @param size The socket receive buffer size option value.
+ **/
+ public void setReceiveBufferSize(int size)
+ {
+ sockProps_.setReceiveBufferSize(size);
+ }
+
+ /**
+ * This property sets the send buffer size socket option to the
+ * specified value. The send buffer size option is used by the
+ * platform's networking code as a hint for the size to set the
+ * underlying network I/O buffers. This value must be greater
+ * than 0.
+ * @param size The socket send buffer size option value.
+ **/
+ public void setSendBufferSize(int size)
+ {
+ sockProps_.setSendBufferSize(size);
+ }
+
+ /**
+ * This property allows the turning on of socket linger with the
+ * specified linger time in seconds. The maxium value for this
+ * property is platform specific.
+ * @param seconds The socket linger option value.
+ **/
+ public void setSoLinger(int seconds)
+ {
+ sockProps_.setSoLinger(seconds);
+ }
+
+ /**
+ * This property enables/disables socket timeout with the
+ * specified value in milliseconds. A timeout value must be
+ * greater than zero, a value of zero for this property indicates
+ * infinite timeout.
+ * @param milliseconds The socket timeout option value.
+ **/
+ public void setSoTimeout(int milliseconds)
+ {
+ sockProps_.setSoTimeout(milliseconds);
+ }
+
+ //@STIMEOUT
+ /**
+ * This property enables/disables socket timeout with the
+ * specified value in milliseconds. A timeout value must be
+ * greater than zero, a value of zero for this property indicates
+ * infinite timeout.
+ * @param milliseconds The socket timeout option value.
+ **/
+ public void setSocketTimeout(int milliseconds)
+ {
+ setSoTimeout(milliseconds);
+ }
+
+ /**
+ * This property allows the turning on of the TCP no delay socket option.
+ * @param noDelay The socket TCP no delay option value.
+ **/
+ public void setTcpNoDelay(boolean noDelay)
+ {
+ sockProps_.setTcpNoDelay(noDelay);
+ }
+ // @F1A End of new socket option methods
+
+ // @M0A - added support for sending statements in UTF-16 and storing them in a UTF-16 package
+ /**
+ * Gets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Default value: 13488
+ * @return The value of the package CCSID property.
+ **/
+ public int getPackageCCSID()
+ {
+ return properties_.getInt(JDProperties.PACKAGE_CCSID);
+ }
+
+ //@dup
+ /**
+ * Gets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Default value: 13488
+ * @return The value of the package CCSID property.
+ * Note: this method is the same as getPackageCCSID() so that it corresponds to the connection property name
+ **/
+ public int getPackageCcsid()
+ {
+ return getPackageCCSID();
+ }
+
+ // @M0A
+ /**
+ * Sets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Recommended values: 1200(UTF-16) and 13488 (UCS-2).
+ * See BidiStringType for Bidi considerations.
+ * Default value: 13488
+ * @param ccsid The package CCSID.
+ **/
+ public void setPackageCCSID(int ccsid)
+ {
+ String property = "packageCCSID";
+
+ Integer oldPackageCCSID = new Integer(getPackageCCSID());
+ Integer newPackageCCSID = new Integer(ccsid);
+
+ validateProperty(property, newPackageCCSID.toString(), JDProperties.PACKAGE_CCSID);
+
+ properties_.setString(JDProperties.PACKAGE_CCSID, newPackageCCSID.toString());
+
+ changes_.firePropertyChange(property, oldPackageCCSID, newPackageCCSID);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + ccsid);
+ }
+
+ //@dup
+ /**
+ * Sets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Recommended values: 1200(UTF-16) and 13488 (UCS-2).
+ * See BidiStringType for Bidi considerations.
+ * Default value: 13488
+ * @param ccsid The package CCSID.
+ * Note: this method is the same as setPackageCCSID() so that it corresponds to the connection property name
+ **/
+ public void setPackageCcsid(int ccsid)
+ {
+ setPackageCCSID(ccsid);
+ }
+
+ // @M0A - added support for 63 digit decimal precision
+ /**
+ * Gets the minimum divide scale property. This property ensures the scale
+ * of the result of decimal division is never less than its specified value.
+ * Valid values: 0-9. 0 is default.
+ * @return The minimum divide scale.
+ **/
+ public int getMinimumDivideScale()
+ {
+ return properties_.getInt(JDProperties.MINIMUM_DIVIDE_SCALE);
+ }
+
+ /**
+ * Gets the maximum block input rows. This property indicates the
+ * number of rows sent to the database engine for a block insert
+ * operation. Valid values: 1-32000. 32000 is default.
+ * @return The maximum block input rows
+ */
+ public int getMaximumBlockedInputRows() {
+ return properties_.getInt(JDProperties.MAXIMUM_BLOCKED_INPUT_ROWS);
+ }
+
+ // @M0A
+ /**
+ * Gets the maximum precision property. This property indicates the
+ * maximum decimal precision the IBM i system should use.
+ * Valid values: 31 or 63. 31 is default.
+ * @return The maximum precision.
+ **/
+ public int getMaximumPrecision()
+ {
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ }
+
+ // @M0A
+ /**
+ * Gets the maximum scale property. This property indicates the
+ * maximum decimal scale the IBM i system should use.
+ * Valid values: 0-63. 31 is default.
+ * @return The maximum scale.
+ **/
+ public int getMaximumScale()
+ {
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ }
+
+ // @M0A
+ /**
+ * Sets the minimum divide scale property. This property ensures the scale
+ * of the result of decimal division is never less than its specified value.
+ * Valid values: 0-9. 0 is default.
+ * @param scale The minimum divide scale.
+ **/
+ public void setMinimumDivideScale(int scale)
+ {
+ String property = "minimumDivideScale";
+
+ Integer oldValue = new Integer(getMinimumDivideScale());
+ Integer newValue = new Integer(scale);
+
+ validateProperty(property, newValue.toString(), JDProperties.MINIMUM_DIVIDE_SCALE);
+
+ properties_.setString(JDProperties.MINIMUM_DIVIDE_SCALE, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + scale);
+ }
+
+ // @A6A
+ /**
+ * Sets the maximum blocked input rows. This property indicates the
+ * maximum number of rows sent to the database engine for a blocked
+ * input operation. Valid values: 1-32000. 32000 is the default
+ * @param maximumBlockedInputRows The maximum number of input rows
+ */
+ public void setMaximumBlockedInputRows(int maximumBlockedInputRows)
+ {
+ String property = "maximumBlockedInputRows";
+
+ Integer oldValue = new Integer(getMaximumBlockedInputRows());
+ Integer newValue = new Integer(maximumBlockedInputRows);
+
+ if (maximumBlockedInputRows < 0 || maximumBlockedInputRows > 32000) {
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ if (maximumBlockedInputRows == 0) {
+ maximumBlockedInputRows = 32000;
+ }
+
+ properties_.setString(JDProperties.MAXIMUM_BLOCKED_INPUT_ROWS, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + maximumBlockedInputRows);
+ }
+
+
+ // @M0A
+ /**
+ * Sets the maximum precision property. This property indicates the
+ * maximum decimal precision the IBM i system should use.
+ * Valid values: 31 or 63. 31 is default.
+ * @param precision The maximum precision.
+ **/
+ public void setMaximumPrecision(int precision)
+ {
+ String property = "maximumPrecision";
+
+ Integer oldValue = new Integer(getMaximumPrecision());
+ Integer newValue = new Integer(precision);
+
+ validateProperty(property, newValue.toString(), JDProperties.MAXIMUM_PRECISION);
+
+ properties_.setString(JDProperties.MAXIMUM_PRECISION, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + precision);
+ }
+
+ // @M0A
+ /**
+ * Sets the maximum scale property. This property indicates the
+ * maximum decimal scale the IBM i system should use.
+ * Valid values: 0-63. 31 is default.
+ * @param scale The maximum scale.
+ **/
+ public void setMaximumScale(int scale)
+ {
+ String property = "maximumScale";
+
+ Integer oldValue = new Integer(getMaximumScale());
+ Integer newValue = new Integer(scale);
+
+ // validate the new value
+ validateProperty(property, newValue.toString(), JDProperties.MAXIMUM_SCALE);
+
+ properties_.setString(JDProperties.MAXIMUM_SCALE, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + scale);
+ }
+
+ // @M0A - added support for hex constant parser option
+ /**
+ * Gets the translate hex property, which indicates how
+ * the parser will treat hexadecimal literals.
+ * @return The value of the translate hex property.
+ *
+ *
+ * The default value is "character".
+ **/
+ public String getTranslateHex()
+ {
+ return properties_.getString(JDProperties.TRANSLATE_HEX);
+ }
+
+ // @M0A
+ /**
+ * Sets the translate hex property, which indicates how
+ * the parser will treat hexadecimal literals.
+ * @param parseOption The hex constant parser option.
+ *
+ *
+ * The default value is "character".
+ **/
+ public void setTranslateHex(String parseOption)
+ {
+ String property = "translateHex";
+
+ String oldOption = getTranslateHex();
+ String newOption = parseOption;
+
+ validateProperty(property, newOption, JDProperties.TRANSLATE_HEX);
+
+ properties_.setString(JDProperties.TRANSLATE_HEX, newOption);
+
+ changes_.firePropertyChange(property, oldOption, newOption);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + parseOption);
+ }
+
+
+ /**
+ * Sets the QAQQINI library name.
+ * @param libraryName The QAQQINI library name.
+ **/
+ public void setQaqqiniLibrary(String libraryName)
+ {
+ String property = "qaqqiniLibrary";
+ if (libraryName == null)
+ throw new NullPointerException(property);
+
+ String old = getQaqqiniLibrary();
+ properties_.setString(JDProperties.QAQQINILIB, libraryName);
+
+ changes_.firePropertyChange(property, old, libraryName);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + libraryName);
+ }
+
+ //@dup
+ /**
+ * Sets the QAQQINI library name.
+ * @param libraryName The QAQQINI library name.
+ * Note: this method is the same as setQaqqiniLibrary() so that it corresponds to the connection property name
+ **/
+ public void setQaqqinilib(String libraryName)
+ {
+ setQaqqiniLibrary(libraryName);
+ }
+
+ /**
+ * Sets the goal the IBM i system should use with optimization of queries.
+ * This setting corresponds with the system's QAQQINI option called OPTIMIZATION_GOAL.
+ * Note, this setting is ignored when running to V5R3 IBM i or earlier
+ * @param goal - the optimization goal
+ *
+ *
+ * The default value is 0.
+ **/
+ public void setQueryOptimizeGoal(int goal)
+ {
+ String property = "queryOptimizeGoal";
+
+ Integer oldValue = new Integer(getQueryOptimizeGoal());
+ Integer newValue = new Integer(goal);
+
+ properties_.setString(JDProperties.QUERY_OPTIMIZE_GOAL, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + goal);
+ }
+
+ //@550
+ /**
+ * Sets 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.
+ * @param limit the storage limit (in megabytes)
+ *
+ *
+ * The default value is "character".
+ **/
+ public void setQueryTimeoutMechanism(String timeoutMechanism)
+ {
+ String property = "queryTimeoutMechanism";
+
+ String oldOption = getQueryTimeoutMechanism();
+ String newOption = timeoutMechanism;
+
+ validateProperty(property, newOption, JDProperties.QUERY_TIMEOUT_MECHANISM);
+
+ properties_.setString(JDProperties.QUERY_TIMEOUT_MECHANISM, newOption);
+
+ changes_.firePropertyChange(property, oldOption, newOption);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + timeoutMechanism);
+ }
+
+
+
+ //@540
+ /**
+ * Sets whether lock sharing is allowed for loosely coupled transaction branches.
+ * Note, this setting is ignored when running to V5R3 IBM i or earlier.
+ * @param lcs - the "loosely coupled support" setting
+ *
+ *
+ * The default value is 0.
+ **/
+ public void setXALooselyCoupledSupport(int lcs)
+ {
+ String property = "xaLooselyCoupledSupport";
+
+ Integer oldValue = new Integer(getXALooselyCoupledSupport());
+ Integer newValue = new Integer(lcs);
+
+ properties_.setString(JDProperties.XA_LOOSELY_COUPLED_SUPPORT, newValue.toString());
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + lcs);
+ }
+
+ //K2A
+ /**
+ * Returns the toolbox trace category.
+ * @return The toolbox trace category.
+ *
+ *
+ **/
+ public String getToolboxTraceCategory()
+ {
+ return properties_.getString(JDProperties.TRACE_TOOLBOX);
+ }
+
+ //@dup
+ /**
+ * Returns the toolbox trace category.
+ * @return The toolbox trace category.
+ *
+ *
+ * Note: this method is the same as getToolboxTraceCategory() so that it corresponds to the connection property name
+ **/
+ public String getToolboxTrace()
+ {
+ return getToolboxTraceCategory();
+ }
+
+ // @K2A
+ /**
+ * Sets the toolbox trace category, which indicates
+ * what trace points and diagnostic messages should be logged.
+ * @param traceCategory The category option.
+ *
+ *
+ * The default value is "none".
+ **/
+ public void setToolboxTraceCategory(String traceCategory)
+ {
+ String property = "toolboxTrace";
+
+ String oldOption = getToolboxTraceCategory();
+ String newOption = traceCategory;
+
+ validateProperty(property, newOption, JDProperties.TRACE_TOOLBOX);
+
+ properties_.setString(JDProperties.TRACE_TOOLBOX, newOption);
+
+ changes_.firePropertyChange(property, oldOption, newOption);
+
+ if(!traceCategory.equals("") && !traceCategory.equals("none"))
+ {
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ if(traceCategory.equals("datastream"))
+ Trace.setTraceDatastreamOn(true);
+ else if(traceCategory.equals("diagnostic"))
+ Trace.setTraceDiagnosticOn(true);
+ else if(traceCategory.equals("error"))
+ Trace.setTraceErrorOn(true);
+ else if(traceCategory.equals("information"))
+ Trace.setTraceInformationOn(true);
+ else if(traceCategory.equals("warning"))
+ Trace.setTraceWarningOn(true);
+ else if(traceCategory.equals("conversion"))
+ Trace.setTraceConversionOn(true);
+ else if(traceCategory.equals("proxy"))
+ Trace.setTraceProxyOn(true);
+ else if(traceCategory.equals("pcml"))
+ Trace.setTracePCMLOn(true);
+ else if(traceCategory.equals("jdbc"))
+ Trace.setTraceJDBCOn(true);
+ else if(traceCategory.equals("all"))
+ Trace.setTraceAllOn(true);
+ else if(traceCategory.equals("thread"))
+ Trace.setTraceThreadOn(true);
+ }
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + traceCategory);
+ }
+
+ //@dup
+ /**
+ * Sets the toolbox trace category, which indicates
+ * what trace points and diagnostic messages should be logged.
+ * @param traceCategory The category option.
+ *
+ *
+ * The default value is "none".
+ * Note: this method is the same as setToolboxTraceCategory() so that it corresponds to the connection property name
+ **/
+ public void setToolboxTrace(String traceCategory)
+ {
+ setToolboxTraceCategory(traceCategory);
+ }
+
+ /**
+ * Validates the property value.
+ * @param property The property name.
+ * @param value The property value.
+ * @param index The property index.
+ **/
+ private void validateProperty(String property, String value, int index)
+ {
+ if (value.length() != 0)
+ { // @A7A
+ DriverPropertyInfo[] info = properties_.getInfo();
+ String[] choices = info[index].choices;
+
+ //Bidi-HCG start
+ //exception for "package ccsid" - it can accept any integer
+ if(index == JDProperties.PACKAGE_CCSID){
+ try{
+ int ccsid = Integer.valueOf(value).intValue();
+ if(ccsid < 1)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ return;
+ }catch(NumberFormatException e){
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ }
+ //Bidi-HCG end
+
+ boolean notValid = true;
+ int current = 0;
+ while (notValid && current < choices.length)
+ {
+ if (value.equalsIgnoreCase(choices[current]))
+ notValid = false;
+ else
+ current++;
+ }
+ if (notValid)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ } // @A7A
+ }
+
+ /**
+ * Serializes the IBM i system and user information.
+ * @param out The output stream.
+ * @exception IOException If a file I/O error occurs.
+ **/
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.writeObject");
+ // @F0D String server = getServerName();
+ // @F0D if (!server.equals(""))
+ // @F0D serialServerName_ = server;
+
+ // @F0D String user = getUser();
+ // @F0D if (!user.equals(""))
+ // @F0D serialUserName_ = user;
+
+ if (!savePasswordWhenSerialized_) //@J3a
+ { //@J3a
+ serialPWBytes_ = null; //@J3a
+ serialKeyRingPWBytes_ = null; //@J3a
+ } //@J3a
+
+ // Serialize the object.
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Returns the string representation of the object.
+ * @return The string representation.
+ **/
+ public String toString()
+ {
+ /*
+ * Implementation note: Used only for tracing information.
+ */
+ String name = getDataSourceName();
+ if (name == null)
+ name = "";
+ return name;
+ }
+
+ // @J3 new method.
+ // Twiddle password bytes.
+ private static char[] xpwConfuse(String info)
+ {
+ Random rng = new Random();
+ byte[] adderBytes = new byte[18];
+ rng.nextBytes(adderBytes);
+ char[] adder = BinaryConverter.byteArrayToCharArray(adderBytes);
+
+ byte[] maskBytes = new byte[14];
+ rng.nextBytes(maskBytes);
+ char[] mask = BinaryConverter.byteArrayToCharArray(maskBytes);
+
+ char[] infoBytes = xencode(adder, mask, info.toCharArray());
+ char[] returnBytes = new char[info.length() + 16];
+ System.arraycopy(adder, 0, returnBytes, 0, 9);
+ System.arraycopy(mask, 0, returnBytes, 9, 7);
+ System.arraycopy(infoBytes, 0, returnBytes, 16, info.length());
+
+ return returnBytes;
+ }
+
+ // @J3 new method.
+ // Get clear password bytes back.
+ private static String xpwDeconfuse(char[] info)
+ {
+ char[] adder = new char[9];
+ System.arraycopy(info, 0, adder, 0, 9);
+ char[] mask = new char[7];
+ System.arraycopy(info, 9, mask, 0, 7);
+ char[] infoBytes = new char[info.length - 16];
+ System.arraycopy(info, 16, infoBytes, 0, info.length - 16);
+
+ return new String(xdecode(adder, mask, infoBytes));
+ }
+
+ // @J3 new method
+ // Scramble some bytes.
+ private static char[] xencode(char[] adder, char[] mask, char[] bytes)
+ {
+ if (bytes == null) return null;
+ int length = bytes.length;
+ char[] buf = new char[length];
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(bytes[i] + adder[i % 9]);
+ }
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(buf[i] ^ mask[i % 7]);
+ }
+ return buf;
+ }
+
+
+ // @J3 new method.
+ private static char[] xdecode(char[] adder, char[] mask, char[] bytes)
+ {
+ int length = bytes.length;
+ char[] buf = new char[length];
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(mask[i % 7] ^ bytes[i]);
+ }
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(buf[i] - adder[i % 9]);
+ }
+ return buf;
+ }
+
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCDataSource", "javax.sql.DataSource" };
+ }
+/* ifdef JDBC40 */
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new SQLFeatureNotSupportedException();
+
+ }
+/* endif */
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCDatabaseMetaData.java b/jdbc40/com/ibm/as400/access/AS400JDBCDatabaseMetaData.java
new file mode 100644
index 000000000..6522ffcf0
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCDatabaseMetaData.java
@@ -0,0 +1,8056 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCDatabaseMetaData.java
+//
+// The source code contained herein is licensed under the IBM Public License
+// Version 1.0, which has been approved by the Open Source Initiative.
+// Copyright (C) 1997-2010 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+/* ifdef JDBC40 */
+import java.sql.RowIdLifetime;
+/* endif */
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.Vector; // @D0A
+
+
+
+
+// @E4C
+/**
+The AS400JDBCDatabaseMetaData class provides information
+about the database as a whole.
+
+
+HELLOWORLD
+HIWORLD
+HWORLD
+HELLOWOULD
+HIWOULD
+
+
+
+
+ @return Always false. Deletes can not be detected
+ by calling ResultSet.rowDeleted().
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean deletesAreDetected (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return false;
+ }
+
+
+
+ /**
+ Indicates if getMaxRowSize() includes blobs when computing the
+ maximum length of a single row.
+
+ @return Always true. getMaxRowSize() does include blobs when
+ computing the maximum length of a single row.
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean doesMaxRowSizeIncludeBlobs ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ //@G4A
+ /**
+ Returns a ResultSet containing a description of type attributes available in a
+ specified catalog.
+
+ This method only applies to the attributes of a
+ structured type. Distinct types are stored in the datatypes
+ catalog, not the attributes catalog. Since DB2 for IBM i does not support
+ structured types at this time, an empty ResultSet will always be returned
+ for calls to this method.
+
+ @param catalog The catalog name.
+ @param schemaPattern The schema name pattern.
+ @param typeNamePattern The type name pattern.
+ @param attributeNamePattern The attribute name pattern.
+
+ @return The empty ResultSet
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public ResultSet getAttributes (String catalog, String schemaPattern,
+ String typeNamePattern, String attributeNamePattern)
+ throws SQLException
+ {
+ // We return an empty result set because this is not supported by our driver
+ Statement statement = connection_.createStatement();
+
+ // TODO: Add this to all methods
+ if (statement instanceof AS400JDBCStatement) {
+ AS400JDBCStatement stmt= (AS400JDBCStatement) statement;
+ stmt.closeOnCompletion();
+ }
+
+ ResultSet rs = statement.executeQuery("SELECT VARCHAR('1', 128) AS TYPE_CAT, " +
+ "VARCHAR('2', 128) AS TYPE_SCHEM, " +
+ "VARCHAR('3', 128) AS TYPE_NAME, " +
+ "VARCHAR('4', 128) AS ATTR_NAME, " +
+ "SMALLINT(5) AS DATA_TYPE, " +
+ "VARCHAR('6', 128) AS ATTR_TYPE_NAME, " +
+ "INT(7) AS ATTR_SIZE, " +
+ "INT(8) AS DECIMAL_DIGITS, " +
+ "INT(9) AS NUM_PREC_RADIX, " +
+ "INT(10) AS NULLABLE, " +
+ "VARCHAR('11', 128) AS REMARKS, " +
+ "VARCHAR('12', 128) AS ATTR_DEF, " +
+ "INT(13) AS SQL_DATA_TYPE, " +
+ "INT(14) AS SQL_DATETIME_SUB, " +
+ "INT(15) AS CHAR_OCTET_LENGTH, " +
+ "INT(16) AS ORDINAL_POSITION, " +
+ "VARCHAR('17', 128) AS IS_NULLABLE, " +
+ "VARCHAR('18', 128) AS SCOPE_CATALOG, " +
+ "VARCHAR('19', 128) AS SCOPE_SCHEMA, " +
+ "VARCHAR('20', 128) AS SCOPE_TABLE, " +
+ "SMALLINT(21) AS SOURCE_DATA_TYPE " +
+ "FROM QSYS2" + getCatalogSeparator() +
+ "SYSTYPES WHERE 1 = 2 FOR FETCH ONLY ");
+
+ return rs;
+ }
+
+
+
+ /**
+ Returns a description of a table's optimal set of columns
+ that uniquely identifies a row.
+
+
+ @param catalog The catalog name. If null is specified, this parameter
+ is ignored. If empty string is specified,
+ an empty result set is returned.
+ @param schema The schema name. If null is specified, the
+ default SQL schema specified in the URL is used.
+ If null is specified and a default SQL schema was not
+ specified in the URL, the first library specified
+ in the libraries properties file is used.
+ If null is specified and a default SQL schema was
+ not specified in the URL and a library was not
+ specified in the libraries properties file,
+ QGPL is used.
+ If empty string is specified, an empty result set will
+ be returned.
+ @param table The table name. If null or empty string is specified,
+ an empty result set is returned.
+ @param scope The scope of interest. Valid values are:
+ bestRowTemporary and bestRowTransaction.
+ bestRowSession is not allowed because
+ it cannot be guaranteed that
+ the row will remain valid for the session.
+ If bestRowSession is specified, an empty result
+ set is returned.
+ If bestRowTransaction is specified,
+ autocommit is false, and transaction is set to repeatable read,
+ then results is returned; otherwise, an empty result set
+ is returned.
+ @param nullable The value indicating if columns that are nullable should be included.
+ @return The ResultSet containing a table's optimal
+ set of columns that uniquely identify a row.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getBestRowIdentifier (String catalog,
+ String schema,
+ String table,
+ int scope,
+ boolean nullable)
+ throws SQLException
+ {
+ connection_.checkOpen ();
+ int vrm = connection_.getVRM(); //@trunc3
+ DBReplyRequestedDS getBestRowIdentifierReply = null;
+
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator () + "SQLSPECIALCOLUMNS(?,?,?,?,?,?,?)");
+
+ cstmt.setShort(1, (short)SQL_BEST_ROWID);
+ cstmt.setString(2, normalize(catalog));
+ cstmt.setString(3, normalize(schema));
+ cstmt.setString(4, normalize(table));
+ cstmt.setShort(5, (short) scope);
+ if (nullable) {
+ cstmt.setShort(6, (short) SQL_NULLABLE);
+ } else {
+ cstmt.setShort(6, (short) SQL_NO_NULLS);
+ }
+ cstmt.setString(7,
+ "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1");
+ cstmt.execute();
+
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+ // Initialize the format of the result set.
+ String[] fieldNames = { "SCOPE",
+ "COLUMN_NAME",
+ "DATA_TYPE",
+ "TYPE_NAME",
+ "COLUMN_SIZE",
+ "BUFFER_LENGTH",
+ "DECIMAL_DIGITS",
+ "PSEUDO_COLUMN",
+ };
+
+ SQLData[] sqlData = { new SQLSmallint (vrm, settings_), // scope //@trunc3
+ new SQLVarchar (128, settings_), // column name
+ new SQLSmallint (vrm, settings_), // data type //@trunc3
+ new SQLVarchar (128, settings_), // type name
+ new SQLInteger (vrm, settings_), // column size //@trunc3
+ new SQLInteger (vrm, settings_), // buffer length //@trunc3
+ new SQLSmallint (vrm, settings_), // decimal digits //@trunc3
+ new SQLSmallint (vrm, settings_), // pseudo column //@trunc3
+ };
+
+ int[] fieldNullables = { columnNoNulls, // scope
+ columnNoNulls, // column name
+ columnNoNulls, // data type
+ columnNoNulls, // type name
+ columnNoNulls, // column size
+ columnNoNulls, // buffer length
+ columnNoNulls, // decimal digits
+ columnNoNulls, // pseudo column
+ };
+
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+
+ JDRowCache rowCache = null;
+ try
+ {
+ // Check for conditions that would result in an empty result set
+ // Must check for null first to avoid NullPointerException
+
+ if (!isCatalogValid(catalog) || // catalog is empty string
+
+ // schema is not null and is empty string
+ ((schema != null) && (schema.length()==0)) ||
+
+ // Table is null
+ (table==null) ||
+
+ // Table is empty string
+ (table.length()==0 ) ||
+
+ // Scope.
+ // If bestRowSession is specified, return empty set
+ // since it can not be guaranteed that the row will
+ // remain valid for the session.
+ // If bestRowTemporary is specified, return results.
+ // If bestRowTransaction is specified and autocommit
+ // is true or transaction is not repeatableRead, return
+ // empty result set
+
+ ((scope == bestRowSession) ||
+
+ ( (scope == bestRowTransaction) &&
+ ( (connection_.getAutoCommit()==true) ||
+ (connection_.getTransactionIsolation() != Connection.TRANSACTION_REPEATABLE_READ)))))
+ { // Return empty result set
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+
+
+ else
+ { // parameter values are valid, build request & send
+ // Create a request
+ //@P0C
+ DBReturnObjectInformationRequestDS request = null;
+ try
+ {
+
+ request = DBDSPool.getDBReturnObjectInformationRequestDS (
+ DBReturnObjectInformationRequestDS.FUNCTIONID_SPECIAL_COLUMN_INFO ,
+ id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA +
+ DBBaseRequestDS.ORS_BITMAP_DATA_FORMAT +
+ DBBaseRequestDS.ORS_BITMAP_RESULT_DATA, 0);
+
+
+
+ // Set the library name
+ if (schema == null)
+ { // use default SQL schema or qgpl
+ request.setLibraryName(connection_.getDefaultSchema(), connection_.converter_); //@P0C
+ }
+ else request.setLibraryName(normalize(schema), connection_.converter_); // @E4C @P0C
+
+ // Set the table name
+ request.setFileName(normalize(table), connection_.converter_); // @E4C @P0C
+
+
+ // Set the Field Information to Return Bitmap
+ // Return library, table, and column
+
+ request.setSpecialColumnsReturnInfoBitmap(0x1F000000);
+
+
+ // Set the short / long file and field name indicator
+ request.setFileShortOrLongNameIndicator(0xF0); // Long
+
+ // Set if columns are nullable
+ request.setSpecialColumnsNullableIndicator(nullable ?
+ 0xF1 : 0xF0);
+
+ //--------------------------------------------------------
+ // Send the request and cache all results from the system
+ //--------------------------------------------------------
+
+ // Dead code
+ // if (getBestRowIdentifierReply != null) {
+ // getBestRowIdentifierReply.returnToPool();
+ // getBestRowIdentifierReply=null;
+ //}
+ getBestRowIdentifierReply = connection_.sendAndReceive(request);
+
+
+ // Check for errors - throw exception if errors were
+ // returned
+ int errorClass = getBestRowIdentifierReply.getErrorClass();
+ if (errorClass !=0)
+ {
+ int returnCode = getBestRowIdentifierReply.getReturnCode();
+ JDError.throwSQLException (this, connection_, id_,
+ errorClass, returnCode);
+ }
+
+ // Get the data format and result data
+ DBDataFormat dataFormat = getBestRowIdentifierReply.getDataFormat();
+ DBData resultData = getBestRowIdentifierReply.getResultData();
+ if (resultData != null)
+ {
+ JDServerRow row = new JDServerRow (connection_, id_, dataFormat, settings_);
+ JDRowCache serverRowCache = new JDSimpleRowCache(new JDServerRowCache(row, connection_, id_, 1, resultData, true, ResultSet.TYPE_SCROLL_INSENSITIVE));
+ JDFieldMap[] maps = new JDFieldMap[8];
+ maps[0] = new JDHardcodedFieldMap(new Short ((short) scope)); // scope
+ maps[1] = new JDSimpleFieldMap (1); // column name
+ maps[2] = new JDDataTypeFieldMap (2, 4, 3, 5, 0, connection_.getVRM(), connection_.getProperties()); // @M0C // data type - converted to short //@KKB pass 0 for ccsid since cannot get ccsid from host server
+ maps[3] = new JDSimpleFieldMap (2); // type name
+ maps[4] = new JDSimpleFieldMap (4); // column size (length)
+ maps[5] = new JDHardcodedFieldMap(new Integer (0)); // buffer length
+ maps[6] = new JDSimpleFieldMap (5); // decimal digits (scale)
+ maps[7] = new JDHardcodedFieldMap(new Short ((short) versionColumnNotPseudo));
+ JDMappedRow mappedRow = new JDMappedRow (formatRow, maps);
+ rowCache = new JDMappedRowCache (mappedRow, serverRowCache);
+ }
+ else
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+ finally
+ {
+ if (request != null) { request.returnToPool(); request = null; }
+ // Cannot return to pool yet because array in use by resultData. Pased to result set to be closed there
+ // if (getBestRowIdentifierReply != null) getBestRowIdentifierReply.returnToPool();
+ }
+ }
+ }
+ catch (DBDataStreamException e)
+ {
+ JDError.throwSQLException (this, JDError.EXC_INTERNAL, e);
+ }
+
+ return new AS400JDBCResultSet (rowCache, connection_.getCatalog(), "BestRowIdentifier", connection_, getBestRowIdentifierReply); //@in2
+ }
+
+
+
+
+
+ /**
+ Returns the catalog name available in this database. This
+ will return a ResultSet with a single row, whose value is
+ the IBM i system name.
+
+ @return The ResultSet containing the IBM i system name.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public ResultSet getCatalogs ()
+ throws SQLException
+ {
+ connection_.checkOpen ();
+
+ //@mdsp SYSIBM SP Call
+ if (connection_.getProperties().getString(JDProperties.METADATA_SOURCE).equals( JDProperties.METADATA_SOURCE_STORED_PROCEDURE))
+ {
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLTABLES(?,?,?,?,?)");
+
+ cstmt.setString(1, "%");
+ cstmt.setString(2, "%");
+ cstmt.setString(3, "%");
+ cstmt.setString(4, "%");
+ cstmt.setString(5, "DATATYPE='JDBC';GETCATALOGS=1;CURSORHOLD=1");
+ cstmt.execute();
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+ String[] fieldNames = {"TABLE_CAT"};
+ SQLData[] sqlData = { new SQLVarchar (128, settings_)};
+ int[] fieldNullables = {columnNoNulls}; // Catalog Name
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+ Object[][] data = { { connection_.getCatalog()}};
+ boolean[][] nulls = {{false}};
+ boolean[][] dataMappingErrors = {{false}};
+
+ // If running to a system running OS/400 v5r2 or IBM i the list can contain more than just the system
+ // name (when IASPs are on the system). Try to retrieve that list. Note
+ // if getting the list fails we will still return a result set containing
+ // one item -- the name of the system. We just built that result set
+ // (the previous six lines of code) and that is what we will return. That
+ // result set will be consistent with the result set returned when connecting
+ // to OS/400 v5r1 or earlier versions. If getting the list works we will
+ // build and return a new result set containing data retrieved from the system.
+ if (connection_.getVRM() >= JDUtilities.vrm520) // @F1a
+ { // @F1a
+ try
+ { // @F1a // @F1a
+ Vector RDBEntries = new Vector(); // @F1a
+
+ Statement statement = null; //@scan1
+ ResultSet rs = null; //@scan1
+ try
+ {
+ statement = connection_.createStatement(); // @F1a
+ rs = statement.executeQuery("SELECT LOCATION FROM QSYS2" + getCatalogSeparator() + "SYSCATALOGS WHERE RDBTYPE = 'LOCAL' AND RDBASPSTAT='AVAILABLE' "); // @F1a
+ while (rs.next()) // @F1a
+ { // @F1a
+ RDBEntries.add(rs.getString(1).trim()); // @F1a
+ }
+ }finally //@scan1
+ {
+ try{
+ if(rs != null)
+ rs.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "getCatalogs rs.close()", e);
+ } //allow next close to execute
+ if(statement != null)
+ statement.close();
+ }
+ int count = RDBEntries.size(); // @F1a
+ if (count > 0) // @F1a
+ { // @F1a
+ data = new Object[count][1]; // @F1a
+ nulls = new boolean[count][1]; // @F1a
+ dataMappingErrors = new boolean[count][1];
+ for (int i=0; i
+
+ @return Always false. Inserts can not be detected
+ by calling ResultSet.rowInserted().
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean insertsAreDetected (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a catalog appears at the start or the end of
+ a qualified name.
+
+ @return Always true. A catalog appears at the start of a
+ qualified name.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean isCatalogAtStart ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the specified catalog is valid for a query.
+ If false is returned, any query using that catalog will
+ be empty since the catalog does not refer to the current
+ connection's catalog.
+
+ @param catalog The catalog name. "" for no catalog
+ or null to drop catalog from the
+ selection criteria.
+ @return true if catalog name is valid; false otherwise
+
+ @exception SQLException This exception is never thrown.
+ **/
+ private boolean isCatalogValid (String catalog)
+ throws SQLException
+ {
+ if (catalog == null)
+ return true;
+
+ return(catalog.equalsIgnoreCase (connection_.getCatalog())
+ || (catalog.equalsIgnoreCase ("localhost")));
+ }
+
+
+
+ /**
+ Indicates if the database is in read-only mode.
+
+ @return true if in read-only mode; false otherwise.
+
+ @exception SQLException If the connection is not open
+ or an error occurs.
+ **/
+ public boolean isReadOnly ()
+ throws SQLException
+ {
+ connection_.checkOpen ();
+ return connection_.isReadOnly ();
+ }
+
+
+ //@F3A
+ /**
+ Indicates if updateable LOB methods update a copy of the LOB or if updates
+ are made directly to the LOB. True is returned if updateable lob methods
+ update a copy of the LOB, false is returned if updates are made directly
+ to the LOB.
+
+ @return Always true. Updateable lob methods update a copy of the LOB.
+ ResultSet.updateRow() must be called to update the LOB in the DB2 for IBM i database.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean locatorsUpdateCopy ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ // @E4A
+ // The database is not case-sensitive except when names are quoted with double
+ // quotes. The host server flows are case-sensitive, so I will uppercase
+ // everything to save the caller from having to do so.
+ private String normalize(String mixedCaseName)
+ {
+ if(mixedCaseName == null) //@mdsp
+ return null; //@mdsp
+
+ if (mixedCaseName.length() > 2)
+ {
+ if (mixedCaseName.charAt(0) == '"')
+ return JDUtilities.stripOutDoubleEmbededQuotes(mixedCaseName); //@PDC mixedCaseName.substring(1, mixedCaseName.length() - 1);
+ }
+ return mixedCaseName.toUpperCase();
+ }
+
+
+
+ /**
+ Indicates if concatenations between null and non-null values
+ are null.
+
+
+ @return Always true. Concatenations between null and non-null
+ values are null.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean nullPlusNonNullIsNull ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if null values are sorted at the end regardless of sort
+ order.
+
+ @return Always false. Null values are not sorted at the end
+ regardless of sort order.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean nullsAreSortedAtEnd ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if null values are sorted at the start regardless of sort
+ order.
+
+ @return Always false. Null values are not sorted at the start
+ regardless of sort order.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean nullsAreSortedAtStart ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if null values are sorted high.
+
+ @return Always true. Null values are sorted high.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean nullsAreSortedHigh ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if null values are sorted low.
+
+ @return Always false. Null values are not sorted low.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean nullsAreSortedLow ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if deletes made by others are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if deletes made by others
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean othersDeletesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if inserts made by others are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if inserts made by others
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean othersInsertsAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if updates made by others are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if updates made by others
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean othersUpdatesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if a result set's own deletes are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if the result set's own deletes
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean ownDeletesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if a result set's own inserts are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if the result set's own inserts
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean ownInsertsAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if a result set's own updates are visible.
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return true if the result set's own updates
+ are visible; false otherwise.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean ownUpdatesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return(resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE);
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, unquoted SQL identifiers
+ as case insensitive and stores them in lowercase.
+
+ @return Always false. The database does not treat mixed case,
+ unquoted SQL identifiers as case insensitive and store
+ them in lowercase.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean storesLowerCaseIdentifiers ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, quoted SQL identifiers
+ as case insensitive and stores them in lowercase.
+
+ @return Always false. The database does not treat mixed case, quoted
+ SQL identifiers as case insensitive and store them in
+ lowercase.
+
+ @exception SQLException This exception is never thrown.
+ */
+ public boolean storesLowerCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, unquoted SQL identifiers
+ as case insensitive and stores them in mixed case.
+
+ @return Always false. The database does not treat mixed case, unquoted
+ SQL identifiers as case insensitive and store them in
+ mixed case.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean storesMixedCaseIdentifiers ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, quoted SQL identifiers
+ as case insensitive and stores them in mixed case.
+
+ @return Always false. The database does not treat mixed case, quoted
+ SQL identifiers as case insensitive and store them in
+ mixed case.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean storesMixedCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ // @A2C changed from false to true
+ return false; //@pdc match other drivers
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, unquoted SQL identifiers
+ as case insensitive and stores them in uppercase.
+
+ @return Always true. The database does treat mixed case, unquoted
+ SQL identifiers as case insensitive and store them
+ in uppercase.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean storesUpperCaseIdentifiers ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, quoted SQL identifiers
+ as case insensitive and stores them in uppercase.
+
+ @return Always false. The database does not treat mixed case, quoted
+ SQL identifiers as case insensitive and store them
+ in uppercase.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean storesUpperCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if ALTER TABLE with ADD COLUMN is supported.
+
+ @return Always true. ALTER TABLE with ADD COLUMN is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsAlterTableWithAddColumn ()
+ throws SQLException
+ {
+ // @A2C Changed from false to true
+ return true;
+ }
+
+
+
+ /**
+ Indicates if ALTER TABLE with DROP COLUMN is supported.
+
+ @return Always true. ALTER TABLE with DROP COLUMN is not supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsAlterTableWithDropColumn ()
+ throws SQLException
+ {
+ // @A2C Changed from false to true
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the ANSI92 entry-level SQL grammar is supported.
+
+ @return Always true. The ANSI92 entry-level SQL grammar is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsANSI92EntryLevelSQL ()
+ throws SQLException
+ {
+ // ANSI92EntryLevelSQL is supported for V4R2 and beyond
+ // true is always returned since it is checked for compliance.
+ return true;
+
+ }
+
+
+
+ /**
+ Indicates if the ANSI92, full SQL grammar is supported.
+
+ @return Always false. ANSI92, full SQL grammar is not supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsANSI92FullSQL ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the ANSI92 intermediate-level SQL grammar is supported.
+
+ @return Always false. ANSI92 intermediate-level SQL grammar is not supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsANSI92IntermediateSQL ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if the batch updates are supported.
+
+ @return Always true. Batch updates are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsBatchUpdates ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a catalog name can be used in a data manipulation
+ statement.
+
+ @return Always false. A catalog name can not be used in a data manipulation
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCatalogsInDataManipulation ()
+ throws SQLException
+ {
+ // @A2 Changed from true to false.
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a catalog name can be used in an index definition
+ statement.
+
+ @return Always false. A catalog name can not be used in an index definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCatalogsInIndexDefinitions ()
+ throws SQLException
+ {
+ // @A2C Changed from true to false
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a catalog name can be used in a privilege definition
+ statement.
+
+ @return Always false. A catalog name can not be used in a privilege definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCatalogsInPrivilegeDefinitions ()
+ throws SQLException
+ {
+ // @A2C Changed from true to false
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a catalog name can be used in a procedure call
+ statement.
+
+ @return Always false. A catalog name can not be used in a procedure call
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCatalogsInProcedureCalls ()
+ throws SQLException
+ {
+ // @A2C Changed from true to false
+ return false;
+ }
+
+
+
+ /**
+ Indicates if a catalog name can be used in a table definition
+ statement.
+
+ @return Always false. A catalog name can not be used in a table definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCatalogsInTableDefinitions ()
+ throws SQLException
+ {
+ // @A2C Changed from true to false
+ return false;
+ }
+
+
+
+ /**
+ Indicates if column aliasing is supported. Column aliasing means
+ that the SQL AS clause can be used to provide names for
+ computed columns or to provide alias names for column
+ as required.
+
+ @return Always true. Column aliasing is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsColumnAliasing ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the CONVERT function between SQL types is supported.
+
+ @return true if the CONVERT function between SQL types is supported;
+ false otherwise.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsConvert ()
+ throws SQLException
+ {
+ return JDEscapeClause.supportsConvert ();
+ }
+
+
+
+ /**
+ Indicates if CONVERT between the given SQL types is supported.
+
+ @param fromType The SQL type code defined in java.sql.Types.
+ @param toType The SQL type code defined in java.sql.Types.
+ @return true if CONVERT between the given SQL types is supported;
+ false otherwise.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsConvert (int fromType, int toType)
+ throws SQLException
+ {
+ return JDEscapeClause.supportsConvert (fromType, toType);
+ }
+
+
+
+ /**
+ Indicates if the ODBC Core SQL grammar is supported.
+
+ @return Always true. The ODBC Core SQL grammar is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCoreSQLGrammar ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the correlated subqueries are supported.
+
+ @return Always true. Correlated subqueries are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsCorrelatedSubqueries ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if both data definition and data manipulation statements
+ are supported within a transaction.
+
+ @return Always true. Data definition and data manipulation statements
+ are both supported within a transaction.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsDataDefinitionAndDataManipulationTransactions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if data manipulation statements are supported within a transaction.
+
+ @return Always false. Data manipulation statements are not supported within
+ a transaction.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsDataManipulationTransactionsOnly ()
+ throws SQLException
+ {
+ // @A2C Changed from true to false
+ return false;
+ }
+
+
+
+ /**
+ Indicates if table correlation names are supported, and if so, are they
+ restricted to be different from the names of the tables.
+
+ @return Always false. Table correlation names are not restricted
+ to be different from the names of the tables.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsDifferentTableCorrelationNames ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if expressions in ORDER BY lists are supported.
+
+ @return Always true. Expression in ORDER BY lists have been supported since V5R2.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsExpressionsInOrderBy ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the ODBC Extended SQL grammar is supported.
+
+ @return Always false. The ODBC Extended SQL grammar is not supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsExtendedSQLGrammar ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if full nested outer joins are supported.
+
+ @return Always false. Full nested outer joins are not supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsFullOuterJoins ()
+ throws SQLException
+ {
+ if(connection_.getVRM() >= JDUtilities.vrm610) //@550
+ return true; //@550
+ else //@550
+ return false;
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates if, after a statement is executed, auto-generated keys can be retrieved
+ using the method Statement.getGeneratedKeys().
+
+ @return True if the user is connecting to a system running OS/400 V5R2
+ or IBM i, otherwise false. Auto-generated keys are supported
+ only if connecting to a system running OS/400 V5R2 or IBM i.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean supportsGetGeneratedKeys ()
+ throws SQLException
+ {
+ if (connection_.getVRM() >= JDUtilities.vrm520)
+ return true;
+ else
+ return false;
+ }
+
+
+
+ /**
+ Indicates if some form of the GROUP BY clause is supported.
+
+ @return Always true. Some form of GROUP BY clause is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsGroupBy ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a GROUP BY clause can add columns not in the SELECT
+ provided it specifies all of the columns in the SELECT.
+
+ @return Always true. A GROUP BY clause can add columns not in the SELECT
+ provided it specifies all of the columns in the SELECT.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsGroupByBeyondSelect ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a GROUP BY clause can use columns not in the SELECT.
+
+ @return Always true. A GROUP BY clause can use columns not in the SELECT.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsGroupByUnrelated ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the SQL Integrity Enhancement Facility is supported.
+
+ @return Always false. The SQL Integrity Enhancement Facility is not
+ supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsIntegrityEnhancementFacility ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the escape character in LIKE clauses is supported.
+
+ @return Always true. The escape character in LIKE clauses is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsLikeEscapeClause ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if there is limited support for outer joins.
+
+ @return Always true. There is limited support for outer joins.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsLimitedOuterJoins ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the ODBC Minimum SQL grammar is supported.
+
+ @return Always true. The ODBC Minimum SQL grammar is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsMinimumSQLGrammar ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, unquoted SQL
+ identifiers as case sensitive and stores
+ them in mixed case.
+
+ @return Always false. The database does not treat mixed case,
+ unquoted SQL identifiers as case sensitive and as
+ a result store them in mixed case.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsMixedCaseIdentifiers ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database treats mixed case, quoted SQL
+ identifiers as case sensitive and as a result stores
+ them in mixed case.
+
+ @return Always true. The database does treat mixed case, quoted SQL
+ identifiers as case sensitive and stores
+ them in mixed case.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsMixedCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates if multiple result sets can be returned from a
+ CallableStatement simultaneously.
+
+ @return Always false. Multiple open result sets from a single execute
+ are not supported by the Toolbox driver.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean supportsMultipleOpenResults ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if multiple result sets from a single execute are
+ supported.
+
+ @return Always true. Multiple result sets from a single execute
+ are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsMultipleResultSets ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if multiple transactions can be open at once (on
+ different connections).
+
+ @return Always true. Multiple transactions can be open at
+ once on different connections.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsMultipleTransactions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates if using parameter names to specify parameters on
+ callable statements are supported.
+
+ @return Always true. An application can use parameter names
+ to specify parameters on callable statements.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean supportsNamedParameters ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if columns can be defined as non-nullable.
+
+ @return Always true. Columns can be defined as non-nullable.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsNonNullableColumns ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if cursors can remain open across commits.
+
+ @return Always true. Cursors can remain open across commits.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOpenCursorsAcrossCommit ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if cursors can remain open across rollback.
+
+ @return Always true. Cursors can remain open across rollback.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOpenCursorsAcrossRollback ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if statements can remain open across commits.
+
+ @return Always true. Statements can remain open across commits.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOpenStatementsAcrossCommit ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if statements can remain open across rollback.
+
+ @return Always true. Statements can remain open across rollback.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOpenStatementsAcrossRollback ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if an ORDER BY clause can use columns not in the SELECT.
+
+ @return Always false. ORDER BY cannot use columns not in the SELECT.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOrderByUnrelated ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if some form of outer join is supported.
+
+ @return Always true. Some form of outer join is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsOuterJoins ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if positioned DELETE is supported.
+
+ @return Always true. Positioned DELETE is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsPositionedDelete ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if positioned UPDATE is supported.
+
+ @return Always true. Positioned UPDATE is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsPositionedUpdate ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ // JDBC 2.0 // @C0C
+ /**
+ Indicates if the specified result set concurrency is supported
+ for the specified result set type.
+
+
+
+
+
+ CONCUR_READ_ONLY CONCUR_UPDATABLE
+ TYPE_FORWARD_ONLY Yes Yes
+ TYPE_SCROLL_INSENSITIVE Yes No
+ TYPE_SCROLL_SENSITIVE Yes Yes
+
+ @param resultSetType The result set type. Valid values are:
+
+
+ @param resultSetConcurrency The result set concurrency. Valid values are:
+
+
+ @return true if the specified result set
+ concurrency is supported for the specified
+ result set type; false otherwise.
+
+ @exception SQLException If the result set type or result set
+ concurrency is not valid.
+ **/
+ //
+ // Implementation note:
+ //
+ // The unsupported combinations are dictated by the DB2
+ // cursor support.
+ //
+ public boolean supportsResultSetConcurrency (int resultSetType, int resultSetConcurrency)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ // Validate the result set concurrency.
+ if ((resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
+ && (resultSetConcurrency != ResultSet.CONCUR_UPDATABLE))
+ JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID);
+
+ // Cases that we don't support.
+ //@K2D if (((resultSetConcurrency == ResultSet.CONCUR_READ_ONLY)
+ //@K2D && (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE))
+ //@K2D || ((resultSetConcurrency == ResultSet.CONCUR_UPDATABLE)
+ //@K2D && (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE)))
+ if((resultSetConcurrency == ResultSet.CONCUR_UPDATABLE) //@K2A
+ && (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE)) //@K2A
+ return false;
+
+ // We support all other cases.
+ return true;
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates if a type of result set holdability is supported. The two
+ types are ResultSet.HOLD_CURSORS_OVER_COMMIT and ResultSet.CLOSE_CURSORS_AT_COMMIT.
+
+ @return True if the user is connecting to a system running OS/400
+ V5R2 or IBM i, otherwise false. Both types of result set
+ holidability are supported if connecting to OS/400 V5R2 or IBM i.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean supportsResultSetHoldability (int resultSetHoldability)
+ throws SQLException
+ {
+ if (connection_.getVRM() >= JDUtilities.vrm520)
+ return true;
+ else
+ return false;
+ }
+
+
+
+ //@G4A
+ /**
+ Indicates if savepoints are supported.
+
+ @return True if the user is connecting to a system running
+ OS/400 V5R2 or IBM i, otherwise false. Savepoints are supported
+ only if connecting to OS/400 V5R2 or IBM i.
+
+ @exception SQLException This exception is never thrown.
+ @since Modification 5
+ **/
+ public boolean supportsSavepoints ()
+ throws SQLException
+ {
+ // Note we check only the system level. We don't need to
+ // check JDBC/JDK level because if running prior to JDBC 3.0
+ // the app cannot call this method (it does not exist
+ // in the interface).
+ if (connection_.getVRM() >= JDUtilities.vrm520)
+ return true;
+ else
+ return false;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if the specified result set type is supported.
+
+ @param resultSetType The result set type. Valid values are:
+
+
+ @return true for ResultSet.TYPE_FORWARD_ONLY
+ ResultSet.TYPE_SCROLL_SENSITIVE. and
+ ResultSet.TYPE_SCROLL_INSENSITIVE.
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean supportsResultSetType (int resultSetType)
+ throws SQLException
+ {
+ switch(resultSetType)
+ {
+ case ResultSet.TYPE_FORWARD_ONLY:
+ case ResultSet.TYPE_SCROLL_SENSITIVE:
+ case ResultSet.TYPE_SCROLL_INSENSITIVE:
+ return true;
+ default:
+ JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID);
+ return false;
+ }
+ }
+
+
+
+ /**
+ Indicates if a schema name can be used in a data manipulation
+ statement.
+
+ @return Always true. A schema name can be used in a data
+ manipulation statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSchemasInDataManipulation ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a schema name can be used in an index definition
+ statement.
+
+ @return Always true. A schema name can be used in an index definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSchemasInIndexDefinitions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a schema name be can used in a privilege definition
+ statement.
+
+ @return Always true. A schema name can be used in a privilege definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSchemasInPrivilegeDefinitions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a schema name be can used in a procedure call
+ statement.
+
+ @return Always true. A schema name can be used in a procedure call
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSchemasInProcedureCalls ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if a schema name can be used in a table definition
+ statement.
+
+ @return Always true. A schema name can be used in a table definition
+ statement.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSchemasInTableDefinitions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if SELECT for UPDATE is supported.
+
+ @return Always true. SELECT for UPDATE is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSelectForUpdate ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ //@B0A - We don't support this directly. Use package caching instead.
+ /**
+ * Indicates if statement pooling is supported.
+ * @return Always false. Statement pooling is not supported at this time.
+ **/
+ public boolean supportsStatementPooling()
+ {
+ return false;
+ }
+
+
+ /**
+ Indicates if stored procedure calls using the stored procedure
+ escape syntax are supported.
+
+ @return Always true. Stored procedure calls using the stored
+ procedure escape syntax are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsStoredProcedures ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+
+ /**
+ Indicates if subqueries in comparisons are supported.
+
+ @return Always true. Subqueries in comparisons are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSubqueriesInComparisons ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if subqueries in EXISTS expressions are supported.
+
+ @return Always true. Subqueries in EXISTS expressions are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSubqueriesInExists ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if subqueries in IN expressions are supported.
+
+ @return Always true. Subqueries in IN expressions are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSubqueriesInIns ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if subqueries in quantified expressions are supported.
+
+ @return Always true. Subqueries in quantified expressions are
+ supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsSubqueriesInQuantifieds ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if table correlation names are supported.
+
+ @return Always true. Table correlation names are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsTableCorrelationNames ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if the database supports the given transaction
+ isolation level.
+
+ @param transactionIsolationLevel One of the Connection.TRANSACTION_*
+ values.
+ @return Always true. All transaction isolation
+ levels are supported.
+
+ @exception SQLException If the transaction isolation level is not valid.
+ **/
+ public boolean supportsTransactionIsolationLevel (int transactionIsolationLevel)
+ throws SQLException
+ {
+ // Validate the transaction isolation level.
+ if ((transactionIsolationLevel != Connection.TRANSACTION_NONE)
+ && (transactionIsolationLevel != Connection.TRANSACTION_READ_UNCOMMITTED)
+ && (transactionIsolationLevel != Connection.TRANSACTION_READ_COMMITTED)
+ && (transactionIsolationLevel != Connection.TRANSACTION_REPEATABLE_READ)
+ && (transactionIsolationLevel != Connection.TRANSACTION_SERIALIZABLE))
+ JDError.throwSQLException (this, JDError.EXC_CONCURRENCY_INVALID);
+
+ if(transactionIsolationLevel == Connection.TRANSACTION_NONE)
+ {
+ return false; // we have determined that we do not support JDBC's idea of TRANSACTION_NONE
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+
+
+ /**
+ Indicates if transactions are supported.
+
+ @return Always true. Transactions are supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsTransactions ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if SQL UNION is supported.
+
+ @return Always true. SQL UNION is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsUnion ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Indicates if SQL UNION ALL is supported.
+
+ @return Always true. SQL UNION ALL is supported.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean supportsUnionAll ()
+ throws SQLException
+ {
+ return true;
+ }
+
+
+
+ /**
+ Returns the name of the catalog.
+
+ @return The name of the catalog.
+ **/
+ public String toString ()
+ {
+ try
+ {
+ return connection_.getCatalog();
+ }
+ catch (SQLException e)
+ {
+ return super.toString ();
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Indicates if visible updates to a result set of the specified type
+ can be detected by calling ResultSet.rowUpdated().
+
+ @param resultSetType The result set type. Value values are:
+
+
+ @return Always false. Updates can not be detected
+ by calling ResultSet.rowUpdated().
+
+ @exception SQLException If the result set type is not valid.
+ **/
+ public boolean updatesAreDetected (int resultSetType)
+ throws SQLException
+ {
+ // Validate the result set type.
+ supportsResultSetType (resultSetType);
+
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database uses a file for each table.
+
+ @return Always false. The database does not use a file for each
+ table.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean usesLocalFilePerTable ()
+ throws SQLException
+ {
+ return false;
+ }
+
+
+
+ /**
+ Indicates if the database stores tables in a local file.
+
+ @return Always false. The database does not store tables in a local
+ file.
+
+ @exception SQLException This exception is never thrown.
+ **/
+ public boolean usesLocalFiles ()
+ throws SQLException
+ {
+ return false;
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCDatabaseMetaData", "java.sql.DatabaseMetaData" };
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Retrieves whether a SQLException
thrown while autoCommit is true
indicates
+ * that all open ResultSets are closed, even ones that are holdable. When a SQLException
occurs while
+ * autocommit is true
, it is vendor specific whether the JDBC driver responds with a commit operation, a
+ * rollback operation, or by doing neither a commit nor a rollback. A potential result of this difference
+ * is in whether or not holdable ResultSets are closed.
+ *
+ * @return true
if so; false
otherwise
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean autoCommitFailureClosesAllResultSets() throws SQLException
+ {
+ return false; //toolbox returns false based on current behavoir
+ }
+
+ //@PDA jdbc40
+ /**
+ * Retrieves a list of the client info properties
+ * that the driver supports. The result set contains the following columns
+ *
+ *
+ *
+ *
+ *
+ * ResultSet
is sorted by the NAME column in ascending order
+ * ResultSet
object; each row is a supported client info
+ * property
+ * ROWID
type,
+ * and if so the lifetime for which a RowId
object remains valid.
+ *
+ * ROWID_UNSUPPORTED < ROWID_VALID_OTHER < ROWID_VALID_TRANSACTION
+ * < ROWID_VALID_SESSION < ROWID_VALID_FOREVER
+ *
+ * so conditional logic such as
+ *
+ * if (metadata.getRowIdLifetime() > DatabaseMetaData.ROWID_VALID_TRANSACTION)
+ *
+ * can be used. Valid Forever means valid across all Sessions, and valid for
+ * a Session means valid across all its contained Transactions.
+ *
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public RowIdLifetime getRowIdLifetime() throws SQLException
+ {
+ return RowIdLifetime.ROWID_VALID_FOREVER; //toolbox rowid is forever
+ }
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ * Retrieves the schema names available in this database. The results
+ * are ordered by schema name.
+ *
+ *
+ *
+ *
+ *
+ * @param catalog a catalog name; must match the catalog name as it is stored
+ * in the database;"" retrieves those without a catalog; null means catalog
+ * name should not be used to narrow down the search.
+ * @param schemaPattern a schema name; must match the schema name as it is
+ * stored in the database; null means
+ * schema name should not be used to narrow down the search.
+ * @return a null
)
+ * ResultSet
object in which each row is a
+ * schema decription
+ * @exception SQLException if a database access error occurs
+ * @see #getSearchStringEscape
+ */
+ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException
+ {
+ connection_.checkOpen();
+
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLTABLES (?, ?, ?, ?, ?)");
+
+ cstmt.setString(1, normalize(catalog));
+ cstmt.setString(2, normalize(schemaPattern));
+ cstmt.setString(3, "%"); //@mdsp
+ cstmt.setString(4, "%"); //@mdsp
+ cstmt.setObject(5, "DATATYPE='JDBC';GETSCHEMAS=2;CURSORHOLD=1");
+ cstmt.execute(); //@mdrs
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Retrieves whether this database supports invoking user-defined or vendor functions
+ * using the stored procedure escape syntax.
+ *
+ * @return true
if so; false
otherwise
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException
+ {
+ // toolbox does not support this
+ return false;
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Retrieves a description of the user functions available in the given
+ * catalog.
+ * FUNCTION_CAT
, FUNCTION_SCHEM
,
+ * FUNCTION_NAME
and
+ * SPECIFIC_ NAME
.
+ *
+ *
+ *
+ * null
)
+ * null
)
+ *
+ *
+ * FUNCTION_NAME
+ * for example with overload functions
+ * getFunctions
+ *
+ * @param catalog a catalog name; must match the catalog name as it
+ * is stored in the database; "" retrieves those without a catalog;
+ * null
means that the catalog name should not be used to narrow
+ * the search
+ * @param schemaPattern a schema name pattern; must match the schema name
+ * as it is stored in the database; "" retrieves those without a schema;
+ * null
means that the schema name should not be used to narrow
+ * the search
+ * @param functionNamePattern a function name pattern; must match the
+ * function name as it is stored in the database
+ * @return ResultSet
- each row is a function description
+ * @exception SQLException if a database access error occurs
+ * @see #getSearchStringEscape
+ */
+ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException
+ {
+ connection_.checkOpen();
+
+ // @A3 Not sure why this was not supported, since the stored procedure exists on V5R4
+ // if(connection_.getVRM() < JDUtilities.vrm610) //@pda HSTSRVR support not PTFing support to v5r4
+ // {
+ // JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ // return null;
+ //}
+
+ /*
+ SYSIBM.SQLFunctions(
+ CatalogName varchar(128),
+ SchemaName varchar(128),
+ FunctionName varchar(128),
+ Options varchar(4000))
+ */
+
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLFUNCTIONS ( ?, ?, ?, ?)");
+
+ cstmt.setString(1, normalize(catalog));
+ cstmt.setString(2, normalize(schemaPattern));
+ cstmt.setString(3, normalize(functionNamePattern));
+ cstmt.setObject(4, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp
+ cstmt.execute(); //@mdrs
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Retrieves a description of the given catalog's system or user
+ * function parameters and return type.
+ *
+ * FUNCTION_CAT
, FUNCTION_SCHEM
,
+ * FUNCTION_NAME
and
+ * SPECIFIC_ NAME
. Within this, the return value,
+ * if any, is first. Next are the parameter descriptions in call
+ * order. The column descriptions follow in column number order.
+ *
+ * ResultSet
+ * is a parameter description, column description or
+ * return type description with the following fields:
+ *
+ *
+ *
+ * null
)
+ * null
)
+ *
+ *
+ * ResultSet
+ *
+ *
+ *
+ *
+ * FUNCTION_NAME
+ * for example with overload functions
+ * null
means that the catalog name should not be used to narrow
+ * the search
+ * @param schemaPattern a schema name pattern; must match the schema name
+ * as it is stored in the database; "" retrieves those without a schema;
+ * null
means that the schema name should not be used to narrow
+ * the search
+ * @param functionNamePattern a procedure name pattern; must match the
+ * function name as it is stored in the database
+ * @param columnNamePattern a parameter name pattern; must match the
+ * parameter or column name as it is stored in the database
+ * @return ResultSet
- each row describes a
+ * user function parameter, column or return type
+ *
+ * @exception SQLException if a database access error occurs
+ * @see #getSearchStringEscape
+ */
+ public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException
+ {
+ //@PDA add support to call stored procedure
+ connection_.checkOpen();
+
+ //@A3D Allow this to occur to V5R4
+ // if(connection_.getVRM() < JDUtilities.vrm610) //@pda HSTSRVR support not PTFing support to v5r4
+ // {
+ // JDError.throwSQLException (this, JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ // return null;
+ // }
+ /*
+ SQLFunctionCols(
+ CatalogName varchar(128),
+ SchemaName varchar(128),
+ FuncName varchar(128),
+ ParamName varchar(128),
+ Options varchar(4000))
+ */
+
+ CallableStatement cstmt = connection_.prepareCall(JDSQLStatement.METADATA_CALL + getCatalogSeparator() + "SQLFUNCTIONCOLS ( ?, ?, ?, ?, ?)");
+
+ cstmt.setString(1, normalize(catalog));
+ cstmt.setString(2, normalize(schemaPattern));
+ cstmt.setString(3, normalize(functionNamePattern));
+ cstmt.setString(4, normalize(columnNamePattern));
+/* ifdef JDBC40 */
+ cstmt.setObject(5, "DATATYPE='JDBC';JDBCVER='4.0';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp //@ver
+/* endif */
+/* ifndef JDBC40
+ cstmt.setObject(5, "DATATYPE='JDBC';DYNAMIC=0;REPORTPUBLICPRIVILEGES=1;CURSORHOLD=1"); //@mdsp
+ endif */
+ cstmt.execute();//@mdrs
+ ResultSet rs = cstmt.getResultSet(); //@mdrs
+ if(rs != null) //@mdrs
+ ((AS400JDBCResultSet)rs).isMetadataResultSet = true;//@mdrs
+ else
+ cstmt.close(); //@mdrs2
+
+ return rs; //@mdrs
+ }
+
+
+ // JDBC 4.1
+ /**
+ * Retrieves whether a generated key will always be returned if the column name(s) or index(es)
+ * specified for the auto generated key column(s) are valid and the statement succeeds.
+ * @return true if so; false otherwise
+ * @exception SQLException - if a database access error occurs
+ */
+
+ public boolean generatedKeyAlwaysReturned() throws SQLException {
+ return false;
+ }
+
+
+
+ // JDBC 4.1
+ /**
+ * Retrieves a description of the pseudo or hidden columns available in a given table within the specified
+ * catalog and schema. Pseudo or hidden columns may not always be stored within a table and are not
+ * visible in a ResultSet unless they are specified in the query's outermost SELECT list. Pseudo or hidden
+ * columns may not necessarily be able to be modified. If there are no pseudo or hidden columns, an empty
+ * ResultSet is returned.
+ *
+ *
+ *
+ *
+ *
+jdbc:as400://system-name/default-schema;properties
+
+
+
+name1=value1;name2=value2;...
+
+See
+JDBC properties
+for a complete list of properties supported by this driver.
+
+
+jdbc:as400://mysystem.helloworld.com/mylibrary;naming=system;errors=full
+
+**/
+//
+// Implementation note:
+//
+// 1. A goal stated in the JDBC specification is to keep
+// the Driver class as small and standalone as possible,
+// so that it can be quickly loaded when choosing a
+// driver for a particular database.
+//
+// 2. It was proposed that we also accept URLs with the
+// "db2" subprotocol. This would make us consistent with
+// other IBM drivers. In addition, it would also allow
+// developers to hardcode URLs in programs and they would
+// run as-is with both this driver and the "native" driver.
+//
+// We realized, though, that if running on a client with
+// both this driver and another DB2 client for that platform,
+// how do the drivers differentiate themselves? Therefore
+// we are chosing NOT to recognized the "db2" subprotocol.
+// Instead, suggest to developers to externalize the URL
+// to users, rather than hardcoding it.
+//
+
+//
+// Note: Change log is now in Copyright.java
+//
+
+
+public class AS400JDBCDriver
+implements java.sql.Driver
+{
+ // Constants.
+
+ static final int MAJOR_VERSION_ = Copyright.MAJOR_VERSION;
+ static final int MINOR_VERSION_ = Copyright.MINOR_VERSION;
+ static final String DATABASE_PRODUCT_NAME_ = "DB2 UDB for AS/400"; // @D0A
+ static final String DRIVER_NAME_ = "AS/400 Toolbox for Java JDBC Driver"; // @D0C @C5C @C6C
+ static final String DRIVER_LEVEL_ = Copyright.DRIVER_LEVEL;
+
+/* ifdef JDBC40 */
+ public static final int JDBC_MAJOR_VERSION_ = 4; // JDBC spec version: 4.0
+/* endif */
+/* ifndef JDBC40
+ public static final int JDBC_MAJOR_VERSION_ = 3; // JDBC spec version: 3.0
+ endif */
+ public static final int JDBC_MINOR_VERSION_ = 0;
+
+
+ // This string "9999:9999" is returned when resource
+ // bundle errors occur. No significance to this string,
+ // except that Client Access used to use it. It would
+ // probably be more helpful to return some other string.
+ //
+ private static final String MRI_NOT_FOUND_ = "9999:9999";
+
+
+
+ // Private data.
+
+ // Toolbox resources needed in proxy jar file. @A1C
+ private static ResourceBundle resources_;
+ // Toolbox resources NOT needed in proxy jar file. @A1A
+ private static ResourceBundle resources2_;
+
+ private static final String CLASSNAME = "com.ibm.as400.access.AS400JDBCDriver";
+
+ private static Driver nativeDriver = null;
+
+
+ /**
+ Static initializer. Registers the JDBC driver with the JDBC
+ driver manager and loads the appropriate resource bundle for
+ the current locale.
+ **/
+ static {
+ try
+ {
+ // Log where the toolbox is loaded from @B1A
+ if (Trace.traceOn_) Trace.logLoadPath(CLASSNAME, Trace.JDBC);
+
+ DriverManager.registerDriver (new AS400JDBCDriver ());
+ resources_ = ResourceBundle.getBundle ("com.ibm.as400.access.JDMRI");
+ resources2_ = ResourceBundle.getBundle ("com.ibm.as400.access.JDMRI2");
+ // Note: When using the proxy jar file, we do not expect to find JDMRI2.
+ }
+ catch (MissingResourceException e)
+ {
+
+ // Catch the exception. This is because exceptions
+ // thrown from static initializers are hard to debug.
+ // Instead, we will handle the error when the
+ // driver needs to get at particular methods.
+ // See getResource().
+ }
+ catch (SQLException e)
+ {
+ // Ignore.
+ }
+ }
+
+
+
+ /**
+ Indicates if the driver understands how to connect
+ to the database named by the URL.
+
+ @param url The URL for the database.
+ @return true if the driver understands how
+ to connect to the database; false
+ otherwise.
+
+ @exception SQLException If an error occurs.
+ **/
+ public boolean acceptsURL (String url)
+ throws SQLException
+ {
+ JDDataSourceURL dataSourceUrl = new JDDataSourceURL (url);
+ return dataSourceUrl.isValid ();
+ }
+
+
+
+ /**
+ Connects to the database named by the specified URL.
+ There are many optional properties that can be specified.
+ 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 this driver.
+
+ @param url The URL for the database.
+ @param info The connection properties.
+ @return The connection to the database or null if
+ the driver does not understand how to connect
+ to the database.
+
+ @exception SQLException If the driver is unable to make the connection.
+ **/
+ public java.sql.Connection connect (String url,
+ Properties info)
+ throws SQLException
+ {
+ // 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.
+ JDDataSourceURL dataSourceUrl = new JDDataSourceURL (url);
+ Properties urlProperties = dataSourceUrl.getProperties ();
+
+ // 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 (urlProperties, info) == JDProperties.TRACE_SET_ON)
+ { //@B5C
+ if (! JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (true);
+ }
+ else if (JDProperties.isTraceSet (urlProperties, info) == JDProperties.TRACE_SET_OFF) //@B5A
+ {
+ //@B5A
+ if (JDTrace.isTraceOn ()) //@B5A
+ JDTrace.setTraceOn (false); //@B5A
+ } //@B5A
+ //@B4D Deleted lines because trace should not be set off just because property
+ //@B4D not specified.
+ //@B4D else
+ //@B4D JDTrace.setTraceOn (false);
+
+ // If toolbox trace is set to datastream. Turn on datastream tracing.
+ if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_DATASTREAM)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceDatastreamOn(true);
+ }
+ // If toolbox trace is set to diagnostic. Turn on diagnostic tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceDiagnosticOn(true);
+ }
+ // If toolbox trace is set to error. Turn on error tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_ERROR)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceErrorOn(true);
+ }
+ // If toolbox trace is set to information. Turn on information tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_INFORMATION)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceInformationOn(true);
+ }
+ // If toolbox trace is set to warning. Turn on warning tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_WARNING)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceWarningOn(true);
+ }
+ // If toolbox trace is set to conversion. Turn on conversion tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_CONVERSION)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceConversionOn(true);
+ }
+ // If toolbox trace is set to proxy. Turn on proxy tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_PROXY)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceProxyOn(true);
+ }
+ // If toolbox trace is set to pcml. Turn on pcml tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_PCML)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTracePCMLOn(true);
+ }
+ // If toolbox trace is set to jdbc. Turn on jdbc tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_JDBC)
+ {
+ //@K1A
+ 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 (urlProperties, info) == JDProperties.TRACE_TOOLBOX_ALL)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceAllOn(true);
+ }
+ // If toolbox trace is set to thread. Turn on thread tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_THREAD)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceThreadOn(true);
+ }
+ // If toolbox trace is set to none. Turn off tracing.
+ else if (JDProperties.isToolboxTraceSet (urlProperties, info) == JDProperties.TRACE_TOOLBOX_NONE)
+ {
+ //@K1A
+ if (Trace.isTraceOn())
+ {
+ Trace.setTraceOn(false);
+ }
+ }
+
+
+ if (JDTrace.isTraceOn()) {
+ String traceUrl = url;
+ int passwordIndex = url.indexOf("password=");
+ if (passwordIndex >= 0) {
+ int semicolonIndex = url.indexOf(";",passwordIndex);
+ if (semicolonIndex < 0) {
+ traceUrl = url.substring(0,passwordIndex)+"password=******";
+ } else {
+ traceUrl = url.substring(0,passwordIndex)+"password=******"+url.substring(semicolonIndex);
+ }
+ }
+ JDTrace.logInformation (this,"connect called with URL: "+traceUrl);
+ }
+
+ JDProperties jdProperties = new JDProperties (urlProperties, info);
+
+ // Initialize the connection if the URL is valid.
+ Connection connection = null; //@A0C
+ if (dataSourceUrl.isValid ())
+ connection = initializeConnection (dataSourceUrl, jdProperties,
+ info); //@A0C
+
+ return connection;
+ }
+
+
+ //@B5A
+ /**
+ Connects to the database on the specified system.
+
+
+
+ @param system The IBM i system to connect.
+ @return The connection to the database or null if
+ the driver does not understand how to connect
+ to the database.
+
+ @exception SQLException If the driver is unable to make the connection.
+ **/
+ public java.sql.Connection connect (AS400 system)
+ throws SQLException
+ {
+ if (system == null)
+ throw new NullPointerException("system");
+
+ if (system instanceof SecureAS400)
+ return initializeConnection(new SecureAS400(system));
+ else
+ return initializeConnection(new AS400(system));
+
+ // Initialize the connection.
+ //@B7D Connection connection = null;
+ //@B7D connection = initializeConnection (o);
+ //@B7D return connection;
+ }
+
+ //@KKB
+ /**
+ Connects to the database on the specified system.
+
+ AS400JDBCDriver d = new AS400JDBCDriver();
+ AS400 o = new AS400(myAS400, myUserId, myPwd);
+ Connection c = d.connect (o);
+
+
+
+ @param system The IBM i system to connect.
+ @param clone True if the AS400 object should be cloned, false otherwises
+ @return The connection to the database or null if
+ the driver does not understand how to connect
+ to the database.
+
+ @exception SQLException If the driver is unable to make the connection.
+ **/
+ public java.sql.Connection connect (AS400 system, boolean clone)
+ throws SQLException
+ {
+ if (system == null)
+ throw new NullPointerException("system");
+
+ if(!clone) //Do not clone the AS400 object, use the one passed in
+ return initializeConnection(system);
+ else //clone the AS400 object
+ return connect(system);
+ }
+
+
+ //@D4A
+ /**
+ Connects to the database on the specified system.
+
+ AS400JDBCDriver d = new AS400JDBCDriver();
+ AS400 o = new AS400(myAS400, myUserId, myPwd);
+ Connection c = d.connect (o, false);
+
+
+
+ @param system The IBM i system to connect.
+ @param info The connection properties.
+ @param schema The default SQL schema or null meaning no default SQL schema specified.
+ @param clone True if the AS400 object should be cloned, false otherwises
+ @return The connection to the database or null if
+ the driver does not understand how to connect
+ to the database.
+
+ @exception SQLException If the driver is unable to make the connection.
+ **/
+ public java.sql.Connection connect (AS400 system, Properties info, String schema, boolean clone)
+ throws SQLException
+ {
+ if (system == null)
+ throw new NullPointerException("system");
+
+ if (info == null)
+ throw new NullPointerException("properties");
+
+ //@PDD not needed, just pass in null to isXTraceSet(null, info) below
+ //Properties urlProperties = new Properties();
+
+ // 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 (null, info) == JDProperties.TRACE_SET_ON)
+ {
+ if (! JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (true);
+ }
+ else if (JDProperties.isTraceSet (null, info) == JDProperties.TRACE_SET_OFF)
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (false);
+ }
+
+ // If toolbox trace is set to datastream. Turn on datastream tracing.
+ if (JDProperties.isToolboxTraceSet (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == 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 (null, info) == JDProperties.TRACE_TOOLBOX_NONE)
+ {
+ if (Trace.isTraceOn())
+ {
+ Trace.setTraceOn(false);
+ }
+ }
+
+ if(!clone) //Do not clone the AS400 object, use the one passed in
+ return initializeConnection(schema, info, system);
+ else //clone the AS400 object
+ {
+ if(system instanceof SecureAS400)
+ return initializeConnection(schema, info, new SecureAS400(system));
+ else
+ return initializeConnection(schema, info, new AS400(system));
+ }
+ }
+
+ //@B5A
+ /**
+ Connects to the database on the specified system.
+ There are many optional properties that can be specified.
+ Properties can be specified in
+ a java.util.Properties object. See
+JDBC properties
+ for a complete list of properties
+ supported by this driver.
+
+
+ AS400JDBCDriver d = new AS400JDBCDriver();
+ AS400 o = new AS400(myAS400, myUserId, myPwd);
+ String mySchema = "defaultSchema";
+ Properties prop = new Properties();
+ Connection c = d.connect (o, prop, mySchema, false);
+
+
+ @param system The IBM i system to connect.
+ @param info The connection properties.
+ @param schema The default SQL schema or null meaning no default SQL schema specified.
+ @return The connection to the database or null if
+ the driver does not understand how to connect
+ to the database.
+
+ @exception SQLException If the driver is unable to make the connection.
+ **/
+ public java.sql.Connection connect (AS400 system, Properties info, String schema)
+ throws SQLException
+ {
+ if (system == null)
+ throw new NullPointerException("system");
+
+ if (info == null)
+ throw new NullPointerException("properties");
+
+ //@B7D AS400 o = new AS400(system);
+ //@PDD not needed, just pass in null to isXTraceSet(null, info) below
+ //Properties urlProperties = new Properties();
+
+ // 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 (null, info) == JDProperties.TRACE_SET_ON)
+ {
+ if (! JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (true);
+ }
+ else if (JDProperties.isTraceSet (null, info) == JDProperties.TRACE_SET_OFF)
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (false);
+ }
+
+ // If toolbox trace is set to datastream. Turn on datastream tracing.
+ if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_DATASTREAM)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceDatastreamOn(true);
+ }
+ // If toolbox trace is set to diagnostic. Turn on diagnostic tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_DIAGNOSTIC)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceDiagnosticOn(true);
+ }
+ // If toolbox trace is set to error. Turn on error tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_ERROR)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceErrorOn(true);
+ }
+ // If toolbox trace is set to information. Turn on information tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_INFORMATION)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceInformationOn(true);
+ }
+ // If toolbox trace is set to warning. Turn on warning tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_WARNING)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceWarningOn(true);
+ }
+ // If toolbox trace is set to conversion. Turn on conversion tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_CONVERSION)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceConversionOn(true);
+ }
+ // If toolbox trace is set to proxy. Turn on proxy tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_PROXY)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceProxyOn(true);
+ }
+ // If toolbox trace is set to pcml. Turn on pcml tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_PCML)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTracePCMLOn(true);
+ }
+ // If toolbox trace is set to jdbc. Turn on jdbc tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_JDBC)
+ {
+ //@K1A
+ 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 (null, info) == JDProperties.TRACE_TOOLBOX_ALL)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceAllOn(true);
+ }
+ // If toolbox trace is set to thread. Turn on thread tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_THREAD)
+ {
+ //@K1A
+ if (! Trace.isTraceOn())
+ {
+ Trace.setTraceOn(true);
+ }
+ Trace.setTraceThreadOn(true);
+ }
+ // If toolbox trace is set to none. Turn off tracing.
+ else if (JDProperties.isToolboxTraceSet (null, info) == JDProperties.TRACE_TOOLBOX_NONE)
+ {
+ //@K1A
+ if (Trace.isTraceOn())
+ {
+ Trace.setTraceOn(false);
+ }
+ }
+
+ //@PDD not used JDProperties jdProperties = new JDProperties (null, info);
+
+ if (system instanceof SecureAS400)
+ return initializeConnection(schema, info, new SecureAS400(system));
+ else
+ return initializeConnection(schema, info, new AS400(system));
+ // Initialize the connection if the URL is valid.
+ //@B7D Connection connection = null;
+ //@B7D connection = initializeConnection (schema, info, o);
+
+ //@B7D return connection;
+ }
+
+
+
+
+ /**
+ Returns the driver's major version number.
+
+ @return The major version number.
+ **/
+ public int getMajorVersion ()
+ {
+ return MAJOR_VERSION_;
+ }
+
+
+
+ /**
+ Returns the driver's minor version number.
+
+ @return The minor version number.
+ **/
+ public int getMinorVersion ()
+ {
+ return MINOR_VERSION_;
+ }
+
+
+
+ /**
+ Returns an array of DriverPropertyInfo objects that
+ describe the properties that are supported by this
+ driver.
+
+ @param url The URL for the database.
+ @param info The connection properties.
+ @return The descriptions of all possible properties or null if
+ the driver does not understand how to connect to the
+ database.
+
+ @exception SQLException If an error occurs.
+ **/
+ public DriverPropertyInfo[] getPropertyInfo (String url,
+ Properties info)
+ throws SQLException
+ {
+ JDDataSourceURL dataSourceUrl = new JDDataSourceURL (url);
+
+ DriverPropertyInfo[] dpi = null;
+ if (dataSourceUrl.isValid ())
+ {
+ JDProperties properties = new JDProperties (dataSourceUrl.getProperties(), info);
+ dpi = properties.getInfo ();
+ }
+
+ return dpi;
+ }
+
+
+
+ /**
+ Returns a resource from the resource bundle.
+
+ @param key The resource key.
+ @return The resource String.
+ **/
+ static String getResource (String key)
+ {
+ // If the resource bundle or resource is not found,
+ // do not thrown an exception. Instead, return a
+ // default string. This is because some JVMs will
+ // not recover quite right from such errors, and
+ // claim a security exception (e.g. Netscape starts
+ // looking in the client class path, which is
+ // not allowed.)
+ //
+ String resource;
+ if (resources_ == null)
+ resource = MRI_NOT_FOUND_;
+ else
+ {
+ try
+ {
+ resource = resources_.getString (key);
+ }
+ catch (MissingResourceException e)
+ {
+ if (resources2_ == null) //@A1A
+ resource = MRI_NOT_FOUND_; //@A1A
+ else
+ { //@A1A
+ try
+ { //@A1A
+ resource = resources2_.getString (key); //@A1A
+ } //@A1A
+ catch (MissingResourceException e1)
+ { //@A1A
+ JDTrace.logInformation (AS400JDBCDriver.class,
+ "Missing resource [" + key + "]"); //@A1A
+ resource = MRI_NOT_FOUND_;
+ }
+ }
+ }
+ }
+
+ return resource;
+ }
+
+
+
+ //@B3A - This logic was formerly in the initializeConnection() method.
+ static AS400 initializeAS400(JDDataSourceURL dataSourceUrl,
+ JDProperties jdProperties,
+ Properties info)
+ throws SQLException //@pw1
+ {
+ // We must handle the different combinations of input
+ // user names and passwords.
+ String serverName = dataSourceUrl.getServerName();
+ String userName = jdProperties.getString (JDProperties.USER);
+ String password = jdProperties.getString (JDProperties.PASSWORD);
+ String prompt = jdProperties.getString (JDProperties.PROMPT); // @B8C
+ boolean secure = jdProperties.getBoolean (JDProperties.SECURE);
+ String keyRingName = jdProperties.getString (JDProperties.KEY_RING_NAME); //@B9A
+ String keyRingPassword = jdProperties.getString (JDProperties.KEY_RING_PASSWORD); //@B9A
+ boolean useThreads = jdProperties.getBoolean(JDProperties.THREAD_USED);
+
+ //@pw1 Decided to leave connections via AS400() as-is and just implement to mimic Native JDBC
+ //@pw1 info contains args from DriverMangager.getConnection(args)
+ //@pw1 jdProperties does not represent null values. Both null and "" have a value of "".
+ //@pw1 if info contains id/pass of "" then they must not be "" in jdProperties (allowing jdProperties to override)
+ //@pw1 throw exception if info id/pass == "" and change info id/pass to "" if they are null
+ //@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)
+ //check if "".
+
+ 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)) || !jdProperties.getBoolean(JDProperties.SECURE_CURRENT_USER)) //@pw3
+ isSecureCurrentUser = false; //@pw3
+
+ if(info == null)
+ info = new Properties();
+ String userParm = info.getProperty("user"); //@pw1
+ String passwordParm = info.getProperty("password"); //@pw1
+ boolean forcePrompt = false; //@prompt
+ if ("".equals(userName) && "".equals(userParm)) //@pw1 //@pw2
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1
+ //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 //@prompt
+ forcePrompt = true; //@prompt
+ } //@pw3
+ } //@pw1
+ if ("".equals(password) && "".equals(passwordParm)) //@pw1 //@pw2
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "Userid/password cannot be \"\" or *CURRENT due to security constraints. Use null instead"); //@pw1
+ //JDError.throwSQLException(JDError.EXC_CONNECTION_REJECTED); //@pw1 //@prompt
+ forcePrompt = true; //@prompt
+ } //@pw3
+ } //@pw1
+
+ if(userParm != null) //@pw1
+ { //@pw1
+ //check for *current //@pw1
+ if (userParm.compareToIgnoreCase("*CURRENT") == 0) //@pw1
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "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
+ } //@pw1
+ else //@pw1
+ { //@pw1
+ //since info is null, jdProperty must not be "" or *current, but it can be the default value (ie not set by user)
+ if(userName != JDProperties.EMPTY_) //@pw1
+ { //@pw1
+ //userName was updated by app
+ if( userName.equals("") || (userName.compareToIgnoreCase("*CURRENT") == 0)) //@pw1
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "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
+ } //@pw1
+ } //@pw1
+
+ if(passwordParm != null) //@pw1
+ { //@pw1
+ if (passwordParm.compareToIgnoreCase("*CURRENT") == 0) //@pw1
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "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
+ } //@pw1
+ else //@pw1
+ { //@pw1
+ //since info is null, jdProperty must not be "" or *current, but it can be the default value (ie not set by user)
+ if(password != JDProperties.EMPTY_) //@pw1
+ { //@pw1
+ //password was updated by app
+ if( password.equals("") || (password.compareToIgnoreCase("*CURRENT") == 0)) //@pw1
+ { //@pw1
+ if(isSecureCurrentUser)//@pw3
+ { //@pw3
+ if (JDTrace.isTraceOn()) //jdbc category trace //@pw1
+ JDTrace.logInformation (AS400JDBCDriver.class, "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
+ } //@pw1
+ } //@pw1
+
+
+ // Create the AS400 object, so we can create a Connection via loadImpl2.
+ AS400 as400 = null;
+ if (secure)
+ {
+ if (serverName.length() == 0)
+ as400 = new SecureAS400 ();
+ else if (userName.length() == 0)
+ as400 = new SecureAS400 (serverName);
+ else if (password.length() == 0)
+ as400 = new SecureAS400 (serverName, userName);
+ else
+ as400 = new SecureAS400 (serverName, userName, password);
+ if (keyRingName != null && keyRingPassword != null && !keyRingName.equals("")) //@B9A @C1C
+ {
+ try
+ { //@B9A
+ ((SecureAS400)as400).setKeyRingName(keyRingName, keyRingPassword); //@B9A
+ } //@B9A
+ catch (PropertyVetoException pve) //@B9A
+ { /*Will never happen*/
+ } //@B9A
+ } //@B9A
+ }
+ else
+ {
+ if (serverName.length() == 0)
+ as400 = new AS400 ();
+ else if (userName.length() == 0)
+ as400 = new AS400 (serverName);
+ else if (password.length() == 0)
+ as400 = new AS400 (serverName, userName);
+ else
+ as400 = new AS400 (serverName, userName, password);
+ }
+
+ // Determine when the signon GUI can be presented..
+ try
+ {
+ if (!prompt.equals(JDProperties.NOT_SPECIFIED)) // @B8A
+ as400.setGuiAvailable(jdProperties.getBoolean(JDProperties.PROMPT)); // @B8C
+ }
+ catch (java.beans.PropertyVetoException e)
+ {
+ // This will never happen, as there are no listeners.
+ }
+
+ //Determine if threads should be used in communication with the host servers
+ try{
+ if(!useThreads)
+ as400.setThreadUsed(useThreads);
+ }
+ catch(java.beans.PropertyVetoException e){
+ }
+ if(forcePrompt) //@prompt
+ as400.forcePrompt(); //@prompt
+ return as400;
+ }
+
+
+ //@A0A - This logic was formerly in the AS400JDBCConnection ctor and open() method.
+ private Connection initializeConnection (JDDataSourceURL dataSourceUrl,
+ JDProperties jdProperties,
+ Properties info)
+ throws SQLException
+ {
+ //@B7D Connection connection = null;
+ AS400 as400 = null;
+ boolean proxyServerWasSpecifiedInUrl = false;
+ boolean proxyServerWasSpecifiedInProperties = false;
+ boolean proxyServerWasSpecified = false;
+
+ //@C4A Check for native driver only if driver property is not set to Toolbox
+ String driverImplementation = jdProperties.getString(JDProperties.DRIVER); //@C4M
+ if (!driverImplementation.equals(JDProperties.DRIVER_TOOLBOX)) //@C4A
+ { //@C4A
+ // @B2A
+ // Determine whether the native driver is available.
+
+ if (nativeDriver == null) {
+ try {
+ nativeDriver = (Driver) Class.forName(
+ "com.ibm.db2.jdbc.app.DB2Driver").newInstance();
+ if (JDTrace.isTraceOn()) // @C2A
+ JDTrace
+ .logInformation(this,
+ "Native IBM Developer Kit for Java JDBC driver implementation was loaded"); // @C2A
+ } catch (Throwable e) {
+ nativeDriver = null;
+ }
+ }
+
+ // @B2A
+ // Decide which JDBC driver implementation to use. If the
+ // native driver is available AND there is no secondary URL
+ // available AND the "driver" property was not set to "toolbox",
+ // then use the native driver implementation.
+ //@C4M String driverImplementation = jdProperties.getString(JDProperties.DRIVER);
+ if ((nativeDriver != null)
+ && (dataSourceUrl.getSecondaryURL().length() == 0))
+ //@C4D Already checked above && (!driverImplementation.equals(JDProperties.DRIVER_TOOLBOX)))
+ {
+ //@C3M
+ boolean isLocal = false; // @C2A
+ String serverName = dataSourceUrl.getServerName(); // @C2A
+ if (serverName.length() == 0 || serverName.equalsIgnoreCase("localhost")) // @C2A //@locala
+ isLocal = true; // @C2A
+ else { // @C2A
+ try { // @C2A
+ InetAddress localInet = InetAddress.getLocalHost(); // @C2A
+ InetAddress[] remoteInet = InetAddress.getAllByName(serverName); // @C2A
+ for (int i = 0; i < remoteInet.length; ++i) { // @C2A
+ if (localInet.equals(remoteInet[i])) { // @C2A
+ isLocal = true; // @C2A
+ } // @C2A
+ } // @C2A
+ } // @C2A
+ catch (Throwable e) { // @C2A
+ // Ignore. We will just assume that we are not local. @C2A
+ } // @C2A
+ }
+
+ if (isLocal) { // @C2A
+ if (JDTrace.isTraceOn()) // @C2A
+ JDTrace.logInformation(this, "Connection is local"); // @C2A
+ String nativeURL = dataSourceUrl.getNativeURL();
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(this, "Using native IBM Developer Kit for Java JDBC driver implementation");//@native don't print passwd
+ return nativeDriver.connect(nativeURL, info);
+ } // @C2A
+ }
+ }//@C4A
+ // @C2D else
+ // @C2D {
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Using IBM Toolbox for Java JDBC driver implementation");
+ // @C2D }
+
+ // @A0A
+ // See if a proxy server was specified.
+ //if (jdProperties.getIndex (JDProperties.PROXY_SERVER) != -1) //@A3D
+ if (jdProperties.getString(JDProperties.PROXY_SERVER).length() != 0) //@A3C
+ proxyServerWasSpecifiedInUrl = true;
+ if (SystemProperties.getProperty (SystemProperties.AS400_PROXY_SERVER) != null)
+ proxyServerWasSpecifiedInProperties = true;
+ if (proxyServerWasSpecifiedInUrl || proxyServerWasSpecifiedInProperties)
+ proxyServerWasSpecified = true;
+
+ // If no proxy server was specified, and there is a secondary URL,
+ // simply pass the secondary URL to the DriverManager and ask it for
+ // an appropriate Connection object.
+ if (!proxyServerWasSpecified)
+ {
+ String secondaryUrl = dataSourceUrl.getSecondaryURL ();
+ if (secondaryUrl.length() != 0)
+ {
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this,
+ "Secondary URL [" + secondaryUrl + "]");
+ return DriverManager.getConnection (secondaryUrl, info);
+ }
+ }
+
+ as400 = initializeAS400(dataSourceUrl, jdProperties, info); // @B3C
+
+ if (proxyServerWasSpecifiedInUrl)
+ {
+ // A proxy server was specified in URL,
+ // so we need to inform the AS400 object.
+
+ //boolean proxyServerSecure = jdProperties.getBoolean (JDProperties.PROXY_SERVER_SECURE); // TBD
+ String proxyServerNameAndPort = jdProperties.getString (JDProperties.PROXY_SERVER);
+ // Note: The PROXY_SERVER property is of the form:
+ // hostName[:portNumber]
+ // where portNumber is optional.
+ try
+ {
+ as400.setProxyServer (proxyServerNameAndPort);
+ //as400.setProxyServerSecure (proxyServerSecure); // TBD
+ }
+ catch (java.beans.PropertyVetoException e)
+ {
+ } // Will never happen.
+ }
+
+ //@B6C Moved common code to prepareConnection.
+ return prepareConnection(as400, dataSourceUrl, info, jdProperties);
+ }
+
+
+ //@B5A
+ private Connection initializeConnection (AS400 as400)
+ throws SQLException
+ {
+ JDDataSourceURL dataSourceUrl = new JDDataSourceURL(null);
+ Properties info = new Properties();
+ JDProperties jdProperties = new JDProperties(null, info);
+
+ //@B6C Moved common code to prepareConnection.
+ return prepareConnection(as400, dataSourceUrl, info, jdProperties);
+ }
+
+
+ //@B5A
+ private Connection initializeConnection (String schema, Properties info, AS400 as400)
+ throws SQLException
+ {
+ boolean proxyServerWasSpecifiedInUrl = false;
+
+ String url = null;
+ if (schema != null) //@B6A
+ url = "jdbc:as400://" + as400.getSystemName() + "/" + schema;
+ else //@B6A
+ url = "jdbc:as400://" + as400.getSystemName(); //@B6A
+ JDDataSourceURL dataSourceUrl = new JDDataSourceURL(url);
+
+ JDProperties jdProperties = new JDProperties(null, info);
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "Using IBM Toolbox for Java JDBC driver implementation");
+
+ // See if a proxy server was specified.
+ if (jdProperties.getString(JDProperties.PROXY_SERVER).length() != 0)
+ proxyServerWasSpecifiedInUrl = true;
+
+ if (proxyServerWasSpecifiedInUrl)
+ {
+ // A proxy server was specified in URL, so we need to inform the AS400 object.
+
+ //boolean proxyServerSecure = jdProperties.getBoolean (JDProperties.PROXY_SERVER_SECURE);// TBD
+ String proxyServerNameAndPort = jdProperties.getString (JDProperties.PROXY_SERVER);
+ // Note: The PROXY_SERVER property is of the form:
+ // hostName[:portNumber]
+ // where portNumber is optional.
+ try
+ {
+ as400.setProxyServer (proxyServerNameAndPort);
+ //as400.setProxyServerSecure (proxyServerSecure); // TBD
+ }
+ catch (java.beans.PropertyVetoException e)
+ {
+ } // Will never happen.
+ }
+
+ //@B6C Moved common code to prepareConnection.
+ return prepareConnection(as400, dataSourceUrl, info, jdProperties);
+ }
+
+
+ /**
+ Indicates if the driver is a genuine JDBC compliant driver.
+
+ @return Always true.
+ **/
+ public boolean jdbcCompliant ()
+ {
+ return true;
+ }
+
+
+ //@B6A -- This logic was formerly in the initializeConnection() method.
+ private Connection prepareConnection(AS400 as400, JDDataSourceURL dataSourceUrl,
+ Properties info, JDProperties jdProperties)
+ throws SQLException
+ {
+
+ // set socket properties
+ SocketProperties sockProps = null;
+
+ //if == "", then take platform defaults...do not set
+ //only get/set properties is one is updated
+ if( jdProperties.getString(JDProperties.KEEP_ALIVE).equals("") == false)
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setKeepAlive(jdProperties.getBoolean(JDProperties.KEEP_ALIVE));
+ }
+ if( jdProperties.getString(JDProperties.RECEIVE_BUFFER_SIZE).equals("") == false)
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setReceiveBufferSize( jdProperties.getInt(JDProperties.RECEIVE_BUFFER_SIZE));
+ }
+ if( jdProperties.getString(JDProperties.SEND_BUFFER_SIZE).equals("") == false)
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setSendBufferSize(jdProperties.getInt(JDProperties.SEND_BUFFER_SIZE));
+ }
+
+ //@timeout2
+ //First get setting from DriverManager, then override with property updates
+ if(!as400.arePropertiesFrozen()) //@timeout3 AS400JDBCDriver.connect(clone=false) cannot update props. We don't know if DriverManager.setLoginTimeout() has been updated.
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setLoginTimeout(DriverManager.getLoginTimeout() * 1000); //@STIMEOUT
+ }
+
+ //@timeout
+ if( jdProperties.getString(JDProperties.LOGIN_TIMEOUT).equals("") == false)
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setLoginTimeout(jdProperties.getInt(JDProperties.LOGIN_TIMEOUT) * 1000); //@STIMEOUT
+ }
+
+ //@STIMEOUT
+ if( jdProperties.getString(JDProperties.SOCKET_TIMEOUT).equals("") == false)
+ {
+ if(sockProps == null)
+ sockProps = as400.getSocketProperties();
+ sockProps.setSoTimeout(jdProperties.getInt(JDProperties.SOCKET_TIMEOUT)); //@STIMEOUT already in milliseconds
+ }
+
+
+ if(sockProps != null)
+ as400.setSocketProperties(sockProps);
+
+ // Create the appropriate kind of Connection object.
+ Connection connection = (Connection) as400.loadImpl2 (
+ "com.ibm.as400.access.AS400JDBCConnection",
+ "com.ibm.as400.access.JDConnectionProxy");
+
+ // Set the properties on the Connection object.
+ if (connection != null)
+ {
+
+ // @A2D Class[] argClasses = new Class[] { JDDataSourceURL.class,
+ // @A2D JDProperties.class,
+ // @A2D AS400.class };
+ // @A2D Object[] argValues = new Object[] { dataSourceUrl,
+ // @A2D jdProperties,
+ // @A2D as400 };
+ // @A2D try {
+ // Hand off the public AS400 object to keep it from getting
+ // garbage-collected.
+ Class clazz = connection.getClass ();
+ // @A2D Method method = clazz.getDeclaredMethod ("setSystem",
+ // @A2D new Class[] { AS400.class });
+ // @A2D method.invoke (connection, new Object[] { as400 });
+
+ // @A2D method = clazz.getDeclaredMethod ("setProperties", argClasses);
+ // @A2D method.invoke (connection, argValues);
+
+ String className = clazz.getName();
+ if (className.equals("com.ibm.as400.access.AS400JDBCConnection"))
+ {
+ ((AS400JDBCConnection)connection).setSystem(as400);
+ ((AS400JDBCConnection)connection).setProperties(dataSourceUrl, jdProperties, as400);
+ }
+ else if (className.equals("com.ibm.as400.access.JDConnectionProxy"))
+ {
+ ((JDConnectionProxy)connection).setSystem(as400);
+ ((JDConnectionProxy)connection).setProperties(dataSourceUrl, jdProperties, as400);
+ }
+ // @A2D }
+ // @A2D catch (NoSuchMethodException e) {
+ // @A2D JDTrace.logInformation (this,
+ // @A2D "Could not resolve setProperties() method");
+ // @A2D throw new InternalErrorException (InternalErrorException.UNEXPECTED_EXCEPTION);
+ // @A2D }
+ // @A2D catch (IllegalAccessException e) {
+ // @A2D JDTrace.logInformation (this,
+ // @A2D "Could not access setProperties() method");
+ // @A2D throw new InternalErrorException (InternalErrorException.UNEXPECTED_EXCEPTION);
+ // @A2D }
+ // @A2D catch (InvocationTargetException e) {
+ // @A2D Throwable e2 = e.getTargetException ();
+ // @A2D if (e2 instanceof SQLException)
+ // @A2D throw (SQLException) e2;
+ // @A2D else if (e2 instanceof RuntimeException)
+ // @A2D throw (RuntimeException) e2;
+ // @A2D else if (e2 instanceof Error)
+ // @A2D throw (Error) e2;
+ // @A2D else {
+ // @A2D JDTrace.logInformation (this,
+ // @A2D "Could not invoke setProperties() method");
+ // @A2D throw new InternalErrorException (InternalErrorException.UNEXPECTED_EXCEPTION);
+ // @A2D }
+ // @A2D }
+ }
+ return connection;
+ }
+
+
+
+
+ /**
+ Returns the name of the driver.
+
+ @return The driver name.
+ **/
+ public String toString ()
+ {
+ return DRIVER_NAME_; // @D0C
+ }
+
+/* ifdef JDBC40 */
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new SQLFeatureNotSupportedException();
+ }
+/* endif */
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCInputStream.java b/jdbc40/com/ibm/as400/access/AS400JDBCInputStream.java
new file mode 100644
index 000000000..51d853f16
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCInputStream.java
@@ -0,0 +1,361 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCInputStream.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.IOException;
+/* ifdef JDBC40 */
+import java.sql.DriverManager;
+/* endif */
+import java.sql.SQLException;
+
+
+
+/**
+
+ AS400JDBCDriver d = new AS400JDBCDriver();
+ String mySchema = "defaultSchema";
+ Properties p = new Properties();
+ AS400 o = new AS400(myAS400, myUserId, myPwd);
+ Connection c = d.connect (o, p, mySchema);
+
+
+ **/
+ public int getBehaviorOverride()
+ {
+ return properties_.getInt(JDProperties.BEHAVIOR_OVERRIDE);
+ }
+
+ /**
+ 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()
+ {
+ String value = properties_.getString(JDProperties.BIDI_STRING_TYPE);
+ try
+ {
+ return Integer.parseInt (value);
+ }
+ catch (NumberFormatException nfe) // if value is "", that is, not set
+ {
+ return -1;
+ }
+ }
+
+
+ /**
+ 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.
+
+
+ **/
+ public int getBlockCriteria()
+ {
+ return properties_.getInt(JDProperties.BLOCK_CRITERIA);
+ }
+
+ /**
+ Returns 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.
+ @return The block size in kilobytes.
+
+
+ **/
+ public int getBlockSize()
+ {
+ return properties_.getInt(JDProperties.BLOCK_SIZE);
+ }
+
+ //@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);
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ Returns a database connection.
+
Note: If a dataSourceName has been specified (via {@link #setDataSourceName setDataSourceName()}, this method will return a pooled connection. Otherwise it will return a non-pooled connection.
+
If the connection pool is at or near capacity, a non-pooled connection may be returned.
+
Note: If a dataSourceName has been specified (via {@link #setDataSourceName setDataSourceName()}, this method will return a pooled connection. Otherwise it will return a non-pooled connection.
+
If the connection pool is at or near capacity, a non-pooled connection may be returned.
+
+
+ The default is "asensitive".
+ This property is ignored when connecting to systems
+ running V5R1 and earlier versions of OS/400.
+ **/
+ public String getCursorSensitivity()
+ {
+ return properties_.getString(JDProperties.CURSOR_SENSITIVITY);
+ }
+
+
+ /**
+ Returns the value of the databaseName property. For more information see
+ the documentation for the setDatabaseName() method in this class.
+ @return The database name.
+ **/
+ public String getDatabaseName()
+ {
+ return properties_.getString(JDProperties.DATABASE_NAME);
+ }
+
+ /**
+ Returns the value of the dataSourceName 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_ == null ? "" : dataSourceName_);
+ }
+
+ /**
+ Returns the date format used in date literals within SQL statements.
+ @return The date format.
+
+
+ The default is based on the server job.
+ **/
+ public String getDateFormat()
+ {
+ return properties_.getString(JDProperties.DATE_FORMAT);
+ }
+
+ /**
+ Returns 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".
+ @return The date separator.
+
+
+ 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.
+
+
+ **/
+ public String getDecfloatRoundingMode()
+ {
+ return properties_.getString(JDProperties.DECFLOAT_ROUNDING_MODE);
+ }
+
+ /**
+ Returns the decimal separator used in numeric literals within SQL statements.
+ @return The decimal separator.
+
+
+ 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_ == null ? "" : description_);
+ }
+
+ /**
+ 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.
+
+
+ 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 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 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.
+ @return The lob threshold. Valid range is 0-16777216.
+ The default value is 32768.
+ **/
+ public int getLobThreshold()
+ {
+ return properties_.getInt(JDProperties.LOB_THRESHOLD);
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ Returns the timeout value in seconds.
+
Note: This value is not used or supported by the Toolbox JDBC driver.
+ Rather, 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);
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ Returns the log writer for this data source.
+ @return The log writer for this data source.
+ @throws 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 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.
+ @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);
+ }
+
+
+ // Note: This method must never be public. It is provided for exclusive use by AS400JDBCManagedConnectionPoolDataSource.
+ /**
+ Returns the password bytes.
+ @return The password bytes.
+ **/
+ final char[] getPWBytes()
+ {
+ return serialPWBytes_;
+ }
+
+ /**
+ Returns the name of the proxy server.
+ @return The proxy server.
+ **/
+ public String getProxyServer()
+ {
+ return properties_.getString(JDProperties.PROXY_SERVER);
+ }
+
+ /**
+ Returns the "query optimize goal" property
+ @return The optimization goal
+
+
+ **/
+ public int getQueryOptimizeGoal()
+ {
+ return properties_.getInt(JDProperties.QUERY_OPTIMIZE_GOAL);
+ }
+
+ /* @D4A */
+ /**
+ * Returns the mechanism used to implement query timeout.
+ * @return the mechanism used to implement query timeout.
+ *
+ *
+ * The default value is 0.
+ **/
+ public String getQueryTimeoutMechanism()
+ {
+ return properties_.getString(JDProperties.QUERY_TIMEOUT_MECHANISM);
+ }
+
+
+
+ //@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
+ *
+ dataSource.setServerTraceCategories(AS400JDBCManagedDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCManagedDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+
+ @return The tracing level.
+
+
+ *
+
+ dataSource.setServerTraceCategories(AS400JDBCManagedDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCManagedDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+
+ @return The tracing level.
+
+
+ *
+
+
+ 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
+ IBM i system.
+ @return The qualified sort table name.
+ **/
+ public String getSortTable()
+ {
+ return properties_.getString(JDProperties.SORT_TABLE);
+ }
+
+ /**
+ Returns how the IBM i 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.
+
+
+ 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.
+
+
+ The default value is based on the server job.
+ **/
+ public String getTimeSeparator()
+ {
+ return properties_.getString(JDProperties.TIME_SEPARATOR);
+ }
+
+
+ /**
+ Returns the IBM i system's transaction isolation.
+ @return The transaction isolation level.
+
+
+ **/
+ public String getTransactionIsolation()
+ {
+ return properties_.getString(JDProperties.TRANSACTION_ISOLATION);
+ }
+
+ /**
+ 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();
+ }
+
+
+ /**
+ Returns the value of the 'user' property.
+ @return The user.
+ **/
+ public String getUser()
+ {
+ //return properties_.getString(JDProperties.USER); //PDD
+ return as400_.getUserId(); //@PDA if running on host, could be default id
+ }
+
+ /**
+ Returns the value of the "XA loosely couple support" property.
+ This indicates whether lock sharing is allowed for loosely coupled transaction branches.
+ @return The "XA loosely coupled support" setting.
+
+
+ **/
+ public int getXALooselyCoupledSupport()
+ {
+ return properties_.getInt(JDProperties.XA_LOOSELY_COUPLED_SUPPORT);
+ }
+
+
+ /**
+ Initializes the connection pool and the built-in pool manager.
+ If dataSourceName property has not been set (via {@link #setDataSourceName setDataSourceName()}, this method does nothing.
+
This method gets called upon the first invocation of {@link #getConnection() getConnection()} or {@link getConnection(String,String) getConnection(user,password)}.
+ @throws SQLException If a database error occurs.
+ **/
+ void initializeConnectionPool() throws SQLException
+ {
+ logWarning("initializeConnectionPool");
+ if (!dataSourceNameSpecified_ && !(this instanceof AS400JDBCManagedConnectionPoolDataSource))
+ {
+ logWarning("No datasource name was specified, so connections will not be pooled");
+ return;
+ }
+ synchronized(this) { /*@A7A */
+ inUse_ = true;
+ }
+ try
+ {
+ if (poolManager_ == null) {
+ if (this instanceof AS400JDBCManagedConnectionPoolDataSource) {
+ cpds_ = (AS400JDBCManagedConnectionPoolDataSource) this;
+ dataSourceNameSpecified_ = true;
+ } else {
+ // Assume that the Context.INITIAL_CONTEXT_FACTORY system property has
+ // been set.
+ Context ctx = new InitialContext();
+ cpds_ = (AS400JDBCManagedConnectionPoolDataSource) ctx
+ .lookup(dataSourceName_);
+ if (cpds_ == null) {
+ logError("Data source name is not bound in JNDI: "
+ + dataSourceName_);
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ }
+ }
+
+ getConnectionPoolKey(); // initialize the default connection pool key
+ poolManager_ = new JDConnectionPoolManager(this, cpds_);
+ // Implementation note: The JNDI lookup() tends to lose the LogWriter
+ // value of cpds_, so we need to give the pool manager access to our own
+ // LogWriter.
+ }
+ } catch (NamingException ne)
+ {
+ ne.printStackTrace();
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ }
+
+ poolManagerInitialized_ = true;
+ }
+
+ /**
+ Initializes the transient data for object de-serialization.
+ **/
+ private final void initializeTransient()
+ {
+ poolManager_ = null;
+ poolManagerInitialized_ = false;
+ defaultConnectionPoolKey_ = null;
+ connectionKeyNeedsUpdate_ = true;
+ if (isSecure_)
+ as400_ = new SecureAS400();
+ else
+ as400_ = new AS400();
+
+ if (sockProps_.isAnyOptionSet()) { // only need to set if not default
+ as400_.setSocketProperties(sockProps_);
+ }
+
+ // Reinitialize the serverName, user, password, keyRingName, etc.
+ if (serialServerName_ != null)
+ setServerName(serialServerName_);
+
+ if (serialUserName_ != null)
+ {
+ setUser(serialUserName_);
+
+ if ((serialPWBytes_ != null) &&
+ (serialPWBytes_.length > 0))
+ {
+ as400_.setPassword(xpwDeconfuse(serialPWBytes_));
+ }
+ }
+
+ try
+ {
+ if (serialKeyRingName_ != null && isSecure_)
+ {
+ if ((serialKeyRingPWBytes_ != null) &&
+ (serialKeyRingPWBytes_.length > 0))
+ {
+ String keyRingPassword = xpwDeconfuse(serialKeyRingPWBytes_);
+ ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_, keyRingPassword);
+ }
+ else
+ {
+ ((SecureAS400)as400_).setKeyRingName(serialKeyRingName_);
+ }
+ }
+ }
+ catch (PropertyVetoException pve) {} // will never happen
+
+ // 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
+ {
+ if (properties_ != null)
+ {
+ if (!isPrompt()) {
+ as400_.setGuiAvailable(false);
+ }
+ }
+ }
+ catch (PropertyVetoException pve) {} // will never happen
+
+ synchronized(this) { //@A7A
+ inUse_ = false;
+ }
+
+ }
+
+ /**
+ Invalidates all pooled connections for the specified user/password.
+ All current available (unallocated) connections for this user/password are closed.
+ As active connections with this user/password are returned to the pool, they are closed.
+ @param user The database user.
+ @param password The database password.
+ **/
+ public void invalidate(String user, String password)
+ {
+ invalidate(user, (password == null ? null : xpwConfuse(password)));
+ }
+
+ /**
+ Invalidates pooled connections for the specified user/password.
+ All current available (unallocated) connections for this user/password are closed.
+ As active (in-use) connections with this user/password are returned to the pool, they are closed.
+ @param user The database user.
+ @param password The database password.
+ **/
+ private final void invalidate(String user, char[] pwBytes)
+ {
+ int hash = (pwBytes == null ? 0 : xpwDeconfuse(pwBytes).hashCode());
+ JDConnectionPoolKey key = new JDConnectionPoolKey(user, hash);
+ if (poolManager_ != null) poolManager_.invalidate(key);
+ }
+
+ //@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);
+ }
+
+ /**
+ 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);
+ }
+
+ /**
+ 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 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.
+ @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);
+ }
+
+ /**
+ 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 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();
+ }
+
+
+ /**
+ 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);
+ }
+
+ /**
+ Returns the value of the "hold input locators" property
+ @return true If input locators are held.
+ **/
+ public boolean isHoldInputLocators()
+ {
+ return properties_.getBoolean(JDProperties.HOLD_LOCATORS);
+ }
+
+
+ /**
+ Returns the value of the "hold statements" property
+ @return true If statements are held.
+ **/
+ public boolean isHoldStatements()
+ {
+ return properties_.getBoolean(JDProperties.HOLD_STATEMENTS);
+ }
+
+
+ /**
+ Indicates whether the pool is in use; that is, whether it contains any connections.
+ Used for checking state conditions. The default is false.
+ @return true if the pool is in use; false otherwise.
+ **/
+ private synchronized final boolean isInUse() // @A7C
+ {
+ return inUse_;
+ }
+
+ //@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);
+ }
+
+ /**
+ 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);
+ }
+
+ /**
+ 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);
+ }
+
+ /**
+ 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()
+ {
+ return false;
+ }
+
+ /**
+ 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);
+ }
+
+ /**
+ Returns the value of the "rollback cursor hold" property.
+ @return true if cursors are held across rollbacks; false otherwise.
+ **/
+ public boolean isRollbackCursorHold()
+ {
+ return properties_.getBoolean(JDProperties.ROLLBACK_CURSOR_HOLD);
+ }
+
+ /**
+ Indicates whether the password is saved locally with the rest of
+ the properties when this data source object is serialized.
+
+
+ The default value is "all".
+ **/
+ public void setAccess(String access)
+ {
+ final String property = "access";
+
+ if (access == null)
+ throw new NullPointerException(property);
+ validateProperty(property, access, JDProperties.ACCESS);
+
+ properties_.setString(JDProperties.ACCESS, access);
+ // Note: The JDProperties.setString() logs the property change.
+ }
+
+
+ //@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)
+ {
+ if (value)
+ properties_.setString(JDProperties.AUTO_COMMIT, TRUE_);
+ else
+ properties_.setString(JDProperties.AUTO_COMMIT, FALSE_);
+
+ }
+
+ //@CE1
+ /**
+ * Sets whether commit or rollback throws SQLException when autocommit is enabled.
+ * @param value
+ * The default value is false.
+ **/
+ public void setAutocommitException(boolean value)
+ {
+ if (value)
+ properties_.setString(JDProperties.AUTOCOMMIT_EXCEPTION, TRUE_);
+ else
+ properties_.setString(JDProperties.AUTOCOMMIT_EXCEPTION, FALSE_);
+
+ }
+
+ /**
+ 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)
+ {
+ if (value)
+ properties_.setString(JDProperties.TRUE_AUTO_COMMIT, TRUE_); //@true
+ else
+ properties_.setString(JDProperties.TRUE_AUTO_COMMIT, FALSE_); //@true
+ }
+
+
+ //@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);
+ }
+
+
+ /**
+ 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.
+
+
+ *
+ 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 thrown 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)
+ {
+ properties_.setString(JDProperties.BEHAVIOR_OVERRIDE, Integer.toString(behaviors));
+ }
+
+ /**
+ Sets the output string type of bidi data. See
+ BidiStringType for more information and valid values.
+ **/
+ public void setBidiStringType(int bidiStringType)
+ {
+ final String property = "bidiStringType";
+
+ validateProperty(property, Integer.toString(bidiStringType), JDProperties.BIDI_STRING_TYPE);
+
+ properties_.setString(JDProperties.BIDI_STRING_TYPE, Integer.toString(bidiStringType));
+ }
+
+ /**
+ 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)
+ {
+ if (value)
+ properties_.setString(JDProperties.BIDI_IMPLICIT_REORDERING, TRUE_);
+ else
+ properties_.setString(JDProperties.BIDI_IMPLICIT_REORDERING, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ if (value)
+ properties_.setString(JDProperties.BIDI_NUMERIC_ORDERING, TRUE_);
+ else
+ properties_.setString(JDProperties.BIDI_NUMERIC_ORDERING, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ if (value)
+ properties_.setString(JDProperties.BIG_DECIMAL, TRUE_);
+ else
+ properties_.setString(JDProperties.BIG_DECIMAL, FALSE_);
+ }
+
+ /**
+ 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.
+
+
+ **/
+ public void setBlockCriteria(int blockCriteria)
+ {
+ final String property = "blockCriteria";
+
+ validateProperty(property, Integer.toString(blockCriteria), JDProperties.BLOCK_CRITERIA);
+
+ properties_.setString(JDProperties.BLOCK_CRITERIA, Integer.toString(blockCriteria));
+ }
+
+ /**
+ 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.
+
+
+ **/
+ public void setBlockSize(int blockSize)
+ {
+ final String property = "blockSize";
+
+ validateProperty(property, Integer.toString(blockSize), JDProperties.BLOCK_SIZE);
+
+ properties_.setString(JDProperties.BLOCK_SIZE, new Integer(blockSize).toString());
+ }
+
+ //@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";
+
+ validateProperty(property, Integer.toString(concurrentAccessResolution), JDProperties.CONCURRENT_ACCESS_RESOLUTION);
+
+ properties_.setString(JDProperties.CONCURRENT_ACCESS_RESOLUTION, Integer.toString(concurrentAccessResolution));
+ }
+
+ /**
+ 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.
+
+
+ The default is "asensitive".
+ This property is ignored when connecting to systems
+ running V5R1 and earlier versions of OS/400.
+ **/
+ public void setCursorSensitivity(String cursorSensitivity)
+ {
+ final String property = "cursorSensitivity";
+
+ validateProperty(property, cursorSensitivity, JDProperties.CURSOR_SENSITIVITY);
+
+ properties_.setString(JDProperties.CURSOR_SENSITIVITY, 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)
+ {
+ if (cursorHold)
+ properties_.setString(JDProperties.CURSOR_HOLD, TRUE_);
+ else
+ properties_.setString(JDProperties.CURSOR_HOLD, FALSE_);
+ }
+
+ /**
+ Sets the databaseName property.
+ This property is ignored when connecting to systems
+ running V5R1 and earlier versions of OS/400.
+ If a database name is specified it must exist in the relational
+ database directory on the IBM i system. Use IBM i command WRKRDBDIRE
+ to view the directory.
+ The following criteria are used to determine
+ which database is accessed:
+
+
+ @param databaseName The database name or *SYSBAS.
+ @throws ExtendedIllegalStateException If the data source is already in use.
+ **/
+ public void setDatabaseName(String databaseName)
+ {
+ final String property = "databaseName";
+
+ if (isInUse()) {
+ logError("Data source is already in use");
+ throw new ExtendedIllegalStateException(property, ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ if (databaseName == null)
+ throw new NullPointerException(property);
+
+ properties_.setString(JDProperties.DATABASE_NAME, databaseName);
+
+ connectionKeyNeedsUpdate_ = true;
+ }
+
+ /**
+ 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)
+ {
+ if (compression)
+ properties_.setString(JDProperties.DATA_COMPRESSION, TRUE_);
+ else
+ properties_.setString(JDProperties.DATA_COMPRESSION, FALSE_);
+ }
+
+ /**
+ Sets the dataSourceName property.
+ This property can be used for connection pooling implementations.
+ dataSourceName is assumed to be bound (via JNDI) to an instance of {@link AS400JDBCManagedConnectionPoolDataSource AS400JDBCManagedConnectionPoolDataSource}.
+
+
+ The default is based on the server job.
+ **/
+ public void setDateFormat(String dateFormat)
+ {
+ final String property = "dateFormat";
+
+ if (dateFormat == null)
+ throw new NullPointerException(property);
+ validateProperty(property, dateFormat, JDProperties.DATE_FORMAT);
+
+ properties_.setString(JDProperties.DATE_FORMAT, dateFormat);
+ }
+
+ /**
+ 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.
+
+
+ The default value is based on the server job.
+ **/
+ public void setDateSeparator(String dateSeparator)
+ {
+ final String property = "dateSeparator";
+ if (dateSeparator == null)
+ throw new NullPointerException(property);
+ validateProperty(property, dateSeparator, JDProperties.DATE_SEPARATOR);
+
+ properties_.setString(JDProperties.DATE_SEPARATOR, dateSeparator);
+ }
+
+ //@DFA
+ /**
+ Sets the decfloat rounding mode.
+ @param decfloatRoundingMode The decfloat rounding mode.
+
+
+ **/
+ public void setDecfloatRoundingMode(String decfloatRoundingMode)
+ {
+ String property = "decfloatRoundingMode";
+ if (decfloatRoundingMode == null)
+ throw new NullPointerException(property);
+ validateProperty(property, decfloatRoundingMode, JDProperties.DECFLOAT_ROUNDING_MODE);
+
+ getDecfloatRoundingMode();
+
+ properties_.setString(JDProperties.DECFLOAT_ROUNDING_MODE, decfloatRoundingMode);
+ }
+
+ /**
+ Sets the decimal separator used in numeric literals within SQL
+ statements.
+ @param decimalSeparator The decimal separator.
+
+
+ The default value is based on the server job.
+ **/
+ public void setDecimalSeparator(String decimalSeparator)
+ {
+ final String property = "decimalSeparator";
+ if (decimalSeparator == null)
+ throw new NullPointerException(property);
+ validateProperty(property, decimalSeparator, JDProperties.DECIMAL_SEPARATOR);
+
+ properties_.setString(JDProperties.DECIMAL_SEPARATOR, decimalSeparator);
+ }
+
+ //@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);
+
+ properties_.setString(JDProperties.IGNORE_WARNINGS, ignoreWarnings);
+ }
+
+ /**
+ Sets the data source description.
+ @param description The description.
+ **/
+ public void setDescription(String description)
+ {
+ final String property = DESCRIPTION;
+ if (description == null)
+ throw new NullPointerException(property);
+
+ description_ = description;
+ logProperty(property, description_);
+ }
+
+ /**
+ Sets how the IBM i system sorts records before sending them to the client.
+ @param sort The sort value.
+
+
+ The default value is "hex".
+ **/
+ public void setSort(String sort)
+ {
+ final 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);
+
+ properties_.setString(JDProperties.SORT, sort);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "errors";
+ if (errors == null)
+ throw new NullPointerException(property);
+ validateProperty(property, errors, JDProperties.ERRORS);
+
+ properties_.setString(JDProperties.ERRORS, errors);
+ }
+
+ /**
+ 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)
+ {
+ if (extendedDynamic)
+ properties_.setString(JDProperties.EXTENDED_DYNAMIC, TRUE_);
+ else
+ properties_.setString(JDProperties.EXTENDED_DYNAMIC, FALSE_);
+ }
+
+ /**
+ Sets whether the driver should request extended metadata from the
+ IBM i system. This property is ignored when connecting to systems
+ running V5R1 and earlier versions of OS/400.
+ If this property is set to true and connecting to a system running
+ V5R2 or later version of 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)
+ {
+ if (extendedMetaData)
+ properties_.setString(JDProperties.EXTENDED_METADATA, TRUE_);
+ else
+ properties_.setString(JDProperties.EXTENDED_METADATA, FALSE_);
+ }
+
+
+
+ //@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);
+ }
+
+
+ /**
+ 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)
+ {
+ if (fullOpen)
+ properties_.setString(JDProperties.FULL_OPEN, TRUE_);
+ else
+ properties_.setString(JDProperties.FULL_OPEN, FALSE_);
+ }
+
+
+ /**
+ Sets the "hold input locators" property
+ @param hold True to hold input locators. The default value is true.
+ **/
+ public void setHoldInputLocators(boolean hold)
+ {
+ if (hold)
+ properties_.setString(JDProperties.HOLD_LOCATORS, TRUE_);
+ else
+ properties_.setString(JDProperties.HOLD_LOCATORS, FALSE_);
+ }
+
+
+ /**
+ Sets the "hold statements" property
+ @param hold True to hold statements. The default value is false.
+ **/
+ public void setHoldStatements(boolean hold)
+ {
+ if (hold)
+ properties_.setString(JDProperties.HOLD_STATEMENTS, TRUE_);
+ else
+ properties_.setString(JDProperties.HOLD_STATEMENTS, FALSE_);
+ }
+
+ //@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)
+ {
+ if (value)
+ properties_.setString(JDProperties.JVM16_SYNCHRONIZE, TRUE_);
+ else
+ properties_.setString(JDProperties.JVM16_SYNCHRONIZE, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ if (lazyClose)
+ properties_.setString(JDProperties.LAZY_CLOSE, TRUE_);
+ else
+ properties_.setString(JDProperties.LAZY_CLOSE, FALSE_);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "libraries";
+ if (libraries == null)
+ throw new NullPointerException(property);
+ properties_.setString(JDProperties.LIBRARIES, libraries);
+ }
+
+ /**
+ 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)
+ {
+ final String property = "threshold";
+ if (threshold < 0 || threshold > MAX_THRESHOLD)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+
+ properties_.setString(JDProperties.LOB_THRESHOLD, new Integer(threshold).toString());
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ 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.
+
Note: This value is not used or supported by the Toolbox JDBC driver.
+ Rather, the timeout value is determined by the IBM i system.
+ @param timeout The login timeout in seconds.
+ **/
+ public void setLoginTimeout(int timeout) throws SQLException
+ {
+ //This sets the socket timeout
+ //@STIMEOUT setSoTimeout(timeout * 1000); //@STIMEOUT separate login and socket timeout into two separtate properties
+
+ properties_.setString(JDProperties.LOGIN_TIMEOUT, Integer.toString(timeout));
+ }
+
+ // method required by javax.sql.DataSource
+ /**
+ Sets the log writer for this data source.
+
+
+ The default value is 0.
+ **/
+ public void setQueryOptimizeGoal(int goal)
+ {
+ String property = "queryOptimizeGoal";
+ validateProperty(property, Integer.toString(goal), JDProperties.QUERY_OPTIMIZE_GOAL);
+
+ properties_.setString(JDProperties.QUERY_OPTIMIZE_GOAL, Integer.toString(goal));
+ }
+
+ /* @D4A*/
+ /**
+ * Sets the query timeout mechanism property, which indicates how
+ * the toolbox will enforce the query timeout specified on the statement.
+ * @param timeoutMechanism The timeout mechanism to use.
+ *
+ *
+ * The default value is "character".
+ **/
+ public void setQueryTimeoutMechanism(String timeoutMechanism)
+ {
+ String property = "queryTimeoutMechanism";
+
+ String newOption = timeoutMechanism;
+
+ validateProperty(property, newOption, JDProperties.QUERY_TIMEOUT_MECHANISM);
+
+ properties_.setString(JDProperties.QUERY_TIMEOUT_MECHANISM, newOption);
+
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, property + ": " + timeoutMechanism);
+ }
+
+
+
+ //@550
+ /**
+ * Sets 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
+ * @param limit - the storage limit (in megabytes)
+ *
+ dataSource.setServerTraceCategories(AS400JDBCManagedDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCManagedDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+
+ @param traceCategories level of tracing to start.
+
+
+
+ dataSource.setServerTraceCategories(AS400JDBCManagedDataSource.SERVER_TRACE_START_DATABASE_MONITOR + AS400JDBCManagedDataSource.SERVER_TRACE_SAVE_SERVER_JOBLOG);
+
+ @param traceCategories level of tracing to start.
+
+
+
+
+ The default value is "toolbox".
+ Note: Not supported in a connection pool.
+ **/
+ public void setDriver(String driver)
+ {
+ final String property = "driver";
+ if (driver == null)
+ throw new NullPointerException(property);
+
+ validateProperty(property, driver, JDProperties.DRIVER);
+
+ properties_.setString(JDProperties.DRIVER, driver);
+ }
+
+ /**
+ Sets whether to save the password locally with the rest of the properties when
+ this data source object is serialized.
+
+
+ The default value is based on the server job.
+ **/
+ public void setTimeFormat(String timeFormat)
+ {
+ final String property = "timeFormat";
+ if (timeFormat == null)
+ throw new NullPointerException(property);
+ validateProperty(property, timeFormat, JDProperties.TIME_FORMAT);
+
+ properties_.setString(JDProperties.TIME_FORMAT, timeFormat);
+ }
+
+ /**
+ 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.
+
+
+ The default value is based on the server job.
+ **/
+ public void setTimeSeparator(String timeSeparator)
+ {
+ final String property = "timeSeparator";
+ if (timeSeparator == null)
+ throw new NullPointerException(property);
+ validateProperty(property, timeSeparator, JDProperties.TIME_SEPARATOR);
+
+ properties_.setString(JDProperties.TIME_SEPARATOR, timeSeparator);
+ }
+
+ /**
+ 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)
+ {
+ if (trace)
+ properties_.setString(JDProperties.TRACE, TRUE_);
+ else
+ properties_.setString(JDProperties.TRACE, FALSE_);
+
+ if (trace)
+ {
+ if (!JDTrace.isTraceOn ())
+ JDTrace.setTraceOn (true);
+ }
+ else
+ JDTrace.setTraceOn (false);
+ }
+
+
+ /**
+ Sets the IBM i system's transaction isolation.
+ @param transactionIsolation The transaction isolation level.
+
+
+ **/
+ public void setTransactionIsolation(String transactionIsolation)
+ {
+ final String property = "transactionIsolation";
+
+ if (transactionIsolation == null)
+ throw new NullPointerException(property);
+ validateProperty(property, transactionIsolation, JDProperties.TRANSACTION_ISOLATION);
+
+ properties_.setString(JDProperties.TRANSACTION_ISOLATION, transactionIsolation);
+ }
+
+ /**
+ 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)
+ {
+ if (translate)
+ properties_.setString(JDProperties.TRANSLATE_BINARY, TRUE_);
+ else
+ properties_.setString(JDProperties.TRANSLATE_BINARY, FALSE_);
+ }
+
+ //@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 if boolean data is translated; false otherwise.
+ * The default value is true.
+ **/
+ public void setTranslateBoolean(boolean translate)
+ {
+ if (translate)
+ properties_.setString(JDProperties.TRANSLATE_BOOLEAN, TRUE_);
+ else
+ properties_.setString(JDProperties.TRANSLATE_BOOLEAN, FALSE_);
+ }
+
+
+ /**
+ Sets the 'user' property.
+ @param user The user.
+ @throws ExtendedIllegalStateException If the data source is already in use.
+ **/
+ public void setUser(String user)
+ {
+ final String property = "user";
+
+ if (isInUse()) {
+ logError("Data source is already in use");
+ throw new ExtendedIllegalStateException(property, ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
+ }
+
+ // save away the user to serialize
+ serialUserName_ = user;
+
+ properties_.setString(JDProperties.USER, user);
+
+ try {
+ as400_.setUserId(user);
+ }
+ catch (PropertyVetoException vp) {} // this will never happen
+
+ connectionKeyNeedsUpdate_ = true;
+ }
+
+ /**
+ Sets whether lock sharing is allowed for loosely coupled transaction branches.
+ Note, this setting is ignored when running to V5R3 IBM i or earlier.
+ @param lcs - the "XA loosely coupled support" setting
+
+
+ The default value is 0.
+ **/
+ public void setXALooselyCoupledSupport(int lcs)
+ {
+ String property = "xaLooselyCoupledSupport";
+ validateProperty(property, Integer.toString(lcs), JDProperties.XA_LOOSELY_COUPLED_SUPPORT);
+
+ properties_.setString(JDProperties.XA_LOOSELY_COUPLED_SUPPORT, Integer.toString(lcs));
+ }
+
+
+ /**
+ Gets the socket 'keepalive' option.
+ @return The value of the keepalive option.
+ **/
+ public boolean isKeepAlive()
+ {
+ return sockProps_.isKeepAlive();
+ }
+
+ /**
+ Gets the socket 'receive buffer size' option. NOTE: This does not get
+ the actual receive buffer size, only the option which is used as a hint
+ by the underlying socket code.
+ @return The value of the receive buffer size option.
+ **/
+ public int getReceiveBufferSize()
+ {
+ return sockProps_.getReceiveBufferSize();
+ }
+
+ /**
+ Gets the socket 'send buffer size' option. NOTE: This does not get
+ the actual send buffer size, only the option which is used as a hint
+ by the underlying socket code.
+ @return The value of the send buffer size option.
+ **/
+ public int getSendBufferSize()
+ {
+ return sockProps_.getSendBufferSize();
+ }
+
+ /**
+ Gets the socket 'linger' option, in milliseconds.
+ @return The value of the linger option.
+ **/
+ public long getSoLinger()
+ {
+ return (long)(1000*sockProps_.getSoLinger());
+ }
+
+ /**
+ Gets the socket 'timeout' option in milliseconds.
+ @return The value of the timeout option.
+ **/
+ public long getSoTimeout()
+ {
+ return (long)sockProps_.getSoTimeout();
+ }
+
+ /**
+ Gets the socket 'TCP no delay' option.
+ @return The value of the TCP no delay option.
+ **/
+ public boolean isTcpNoDelay()
+ {
+ return sockProps_.isTcpNoDelay();
+ }
+
+ /**
+ Turns on the socket 'keepAlive' property.
+ @param keepAlive The keepalive option value.
+ **/
+ public void setKeepAlive(boolean keepAlive)
+ {
+ sockProps_.setKeepAlive(keepAlive);
+ logProperty("keepAlive", String.valueOf(keepAlive)); //@jvm13 Boolean.toString(keepAlive));
+ }
+
+ /**
+ Sets the socket 'receive buffer size' option to the
+ specified value. The receive buffer size option is used as a hint
+ for the size to set the underlying network I/O buffers. Increasing
+ the receive buffer size can increase the performance of network
+ I/O for high-volume connection, while decreasing it can help reduce
+ the backlog of incoming data. This value must be greater than 0.
+ @param size The receive buffer size option value.
+ **/
+ public void setReceiveBufferSize(int size)
+ {
+ sockProps_.setReceiveBufferSize(size);
+ logProperty("receiveBufferSize", Integer.toString(size));
+ }
+
+ /**
+ Sets the socket 'send buffer size' option to the
+ specified value. The send buffer size option is used by the
+ platform's networking code as a hint for the size to set the
+ underlying network I/O buffers. This value must be greater
+ than 0.
+ @param size The send buffer size option value.
+ **/
+ public void setSendBufferSize(int size)
+ {
+ sockProps_.setSendBufferSize(size);
+ logProperty("sendBufferSize", Integer.toString(size));
+ }
+
+ /**
+ Sets the socket 'linger' property to the
+ specified linger time in milliseconds. The maximum value for this
+ property is platform specific.
+ @param milliseconds The linger option value.
+ **/
+ public void setSoLinger(long milliseconds)
+ {
+ final String property = "soLinger";
+
+ if (milliseconds > Integer.MAX_VALUE)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+
+ sockProps_.setSoLinger((int)(milliseconds/1000)); // called method expects seconds
+ logProperty(property, Long.toString(milliseconds));
+ }
+
+ /**
+ Enables/disables socket timeout with the
+ specified value in milliseconds. A timeout value must be
+ greater than zero, a value of zero for this property indicates
+ infinite timeout.
+ @param milliseconds The timeout option value.
+ **/
+ public void setSoTimeout(long milliseconds)
+ {
+ final String property = "soTimeout";
+
+ if (milliseconds > Integer.MAX_VALUE)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+
+ sockProps_.setSoTimeout((int)milliseconds);
+ logProperty(property, Long.toString(milliseconds));
+ }
+
+ /**
+ Sets the socket 'TCP no delay' option.
+ @param noDelay The TCP no delay option value.
+ **/
+ public void setTcpNoDelay(boolean noDelay)
+ {
+ sockProps_.setTcpNoDelay(noDelay);
+ logProperty("tcpNoDelay", String.valueOf(noDelay)); //@jvm13 Boolean.toString(noDelay));
+ }
+
+ /**
+ Gets the package CCSID property, which indicates the
+ CCSID in which statements are sent to the IBM i system and
+ also the CCSID of the package they are stored in.
+ Default value: 13488
+ @return The value of the package CCSID property.
+ **/
+ public int getPackageCCSID()
+ {
+ return properties_.getInt(JDProperties.PACKAGE_CCSID);
+ }
+
+
+ //@dup
+ /**
+ * Gets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Default value: 13488
+ * @return The value of the package CCSID property.
+ * Note: this method is the same as getPackageCCSID() so that it corresponds to the connection property name
+ **/
+ public int getPackageCcsid()
+ {
+ return getPackageCCSID();
+ }
+
+
+ /**
+ Sets the package CCSID property, which indicates the
+ CCSID in which statements are sent to the IBM i system and
+ also the CCSID of the package they are stored in.
+ Recommended values: 1200(UTF-16) and 13488 (UCS-2).
+ See BidiStringType for Bidi considerations.
+ Default value: 13488
+ @param ccsid The package CCSID.
+ **/
+ public void setPackageCCSID(int ccsid)
+ {
+ final String property = "packageCCSID";
+
+ validateProperty(property, Integer.toString(ccsid), JDProperties.PACKAGE_CCSID);
+
+ properties_.setString(JDProperties.PACKAGE_CCSID, Integer.toString(ccsid));
+ }
+
+ //@dup
+ /**
+ * Sets the package CCSID property, which indicates the
+ * CCSID in which statements are sent to the IBM i system and
+ * also the CCSID of the package they are stored in.
+ * Recommended values: 1200(UTF-16) and 13488 (UCS-2).
+ * See BidiStringType for Bidi considerations.
+ * Default value: 13488
+ * @param ccsid The package CCSID.
+ * Note: this method is the same as setPackageCCSID() so that it corresponds to the connection property name
+ **/
+ public void setPackageCcsid(int ccsid)
+ {
+ setPackageCCSID(ccsid);
+ }
+
+
+ /**
+ Gets the minimum divide scale property. This property ensures the scale
+ of the result of decimal division is never less than its specified value.
+ Valid values: 0-9. 0 is default.
+ @return The minimum divide scale.
+ **/
+ public int getMinimumDivideScale()
+ {
+ return properties_.getInt(JDProperties.MINIMUM_DIVIDE_SCALE);
+ }
+
+ /**
+ * Gets the maximum block input rows. This property indicates the
+ * number of rows sent to the database engine for a block insert
+ * operation. Valid values: 1-32000. 32000 is default.
+ * @return The maximum block input rows
+ */
+ public int getMaximumBlockedInputRows()
+ {
+ return properties_.getInt(JDProperties.MAXIMUM_BLOCKED_INPUT_ROWS);
+ }
+
+
+
+ /**
+ Gets the maximum precision property. This property indicates the
+ maximum decimal precision the IBM i system should use.
+ Valid values: 31 or 63. 31 is default.
+ @return The maximum precision.
+ **/
+ public int getMaximumPrecision()
+ {
+ return properties_.getInt(JDProperties.MAXIMUM_PRECISION);
+ }
+
+ /**
+ Gets the maximum scale property. This property indicates the
+ maximum decimal scale the IBM i system should use.
+ Valid values: 0-63. 31 is default.
+ @return The maximum scale.
+ **/
+ public int getMaximumScale()
+ {
+ return properties_.getInt(JDProperties.MAXIMUM_SCALE);
+ }
+
+ /**
+ Sets the minimum divide scale property. This property ensures the scale
+ of the result of decimal division is never less than its specified value.
+ Valid values: 0-9. 0 is default.
+ @param scale The minimum divide scale.
+ **/
+ public void setMinimumDivideScale(int scale)
+ {
+ final String property = "minimumDivideScale";
+
+ validateProperty(property, Integer.toString(scale), JDProperties.MINIMUM_DIVIDE_SCALE);
+
+ properties_.setString(JDProperties.MINIMUM_DIVIDE_SCALE, Integer.toString(scale));
+ }
+
+
+ // @A6A
+ /**
+ * Sets the maximum blocked input rows. This property indicates the
+ * maximum number of rows sent to the database engine for a blocked
+ * input operation. Valid values: 1-32000. 32000 is the default
+ * @param maximumBlockedInputRows The maximum number of input rows
+ */
+
+ public void setMaximumBlockedInputRows(int maximumBlockedInputRows)
+ {
+ final String property = "maximumBlockedInputRows";
+
+ validateProperty(property, Integer.toString(maximumBlockedInputRows), JDProperties.MAXIMUM_BLOCKED_INPUT_ROWS);
+
+ properties_.setString(JDProperties.MAXIMUM_PRECISION, Integer.toString(maximumBlockedInputRows));
+ }
+
+
+ /**
+ Sets the maximum precision property. This property indicates the
+ maximum decimal precision the IBM i system should use.
+ Valid values: 31 or 63. 31 is default.
+ @param precision The maximum precision.
+ **/
+ public void setMaximumPrecision(int precision)
+ {
+ final String property = "maximumPrecision";
+
+ validateProperty(property, Integer.toString(precision), JDProperties.MAXIMUM_PRECISION);
+
+ properties_.setString(JDProperties.MAXIMUM_PRECISION, Integer.toString(precision));
+ }
+
+ /**
+ Sets the maximum scale property. This property indicates the
+ maximum decimal scale the IBM i system should use.
+ Valid values: 0-63. 31 is default.
+ @param scale The maximum scale.
+ **/
+ public void setMaximumScale(int scale)
+ {
+ final String property = "maximumScale";
+
+ // validate the new value
+ validateProperty(property, Integer.toString(scale), JDProperties.MAXIMUM_SCALE);
+
+ properties_.setString(JDProperties.MAXIMUM_SCALE, Integer.toString(scale));
+ }
+
+ /**
+ Gets the translate hex property, which indicates how
+ the parser will treat hexadecimal literals.
+ @return The value of the translate hex property.
+
+
+ The default value is "character".
+ **/
+ public String getTranslateHex()
+ {
+ return properties_.getString(JDProperties.TRANSLATE_HEX);
+ }
+
+ /**
+ Sets the translate hex property, which indicates how
+ the parser will treat hexadecimal literals.
+ @param parseOption The hex constant parser option.
+
+
+ The default value is "character".
+ **/
+ public void setTranslateHex(String parseOption)
+ {
+ final String property = "translateHex";
+
+ validateProperty(property, parseOption, JDProperties.TRANSLATE_HEX);
+
+ properties_.setString(JDProperties.TRANSLATE_HEX, parseOption);
+ }
+
+ /**
+ Sets the QAQQINI library name.
+ @param libraryName The QAQQINI library name.
+ **/
+ public void setQaqqiniLibrary(String libraryName)
+ {
+ final String property = "qaqqiniLibrary";
+ if (libraryName == null)
+ throw new NullPointerException(property);
+
+ properties_.setString(JDProperties.QAQQINILIB, libraryName);
+ }
+
+ //@dup
+ /**
+ * Sets the QAQQINI library name.
+ * @param libraryName The QAQQINI library name.
+ * Note: this method is the same as setQaqqiniLibrary() so that it corresponds to the connection property name
+ **/
+ public void setQaqqinilib(String libraryName)
+ {
+ setQaqqiniLibrary(libraryName);
+ }
+
+ /**
+ Returns the toolbox trace category.
+ @return The toolbox trace category.
+
+
+ **/
+ public String getToolboxTraceCategory()
+ {
+ return properties_.getString(JDProperties.TRACE_TOOLBOX);
+ }
+
+
+ //@dup
+ /**
+ * Returns the toolbox trace category.
+ * @return The toolbox trace category.
+ *
+ *
+ * Note: this method is the same as getToolboxTraceCategory() so that it corresponds to the connection property name
+ **/
+ public String getToolboxTrace()
+ {
+ return getToolboxTraceCategory();
+ }
+
+
+ /**
+ Sets the toolbox trace category, which indicates
+ what trace points and diagnostic messages should be logged.
+ @param traceCategory The category option.
+
+
+ The default value is "none".
+ **/
+ public void setToolboxTraceCategory(String traceCategory)
+ {
+ final String property = "toolboxTrace";
+
+ validateProperty(property, traceCategory, JDProperties.TRACE_TOOLBOX);
+
+ properties_.setString(JDProperties.TRACE_TOOLBOX, traceCategory);
+ }
+
+
+ //@dup
+ /**
+ * Sets the toolbox trace category, which indicates
+ * what trace points and diagnostic messages should be logged.
+ * @param traceCategory The category option.
+ *
+ *
+ * The default value is "none".
+ * Note: this method is the same as setToolboxTraceCategory() so that it corresponds to the connection property name
+ **/
+ public void setToolboxTrace(String traceCategory)
+ {
+ setToolboxTraceCategory(traceCategory);
+ }
+
+ /**
+ Validates the property value.
+ @param property The property name.
+ @param value The property value.
+ @param index The property index.
+ **/
+ private final void validateProperty(String property, String value, int index)
+ {
+ if (value.length() != 0)
+ {
+ DriverPropertyInfo[] info = properties_.getInfo();
+ String[] choices = info[index].choices;
+
+ //Bidi-HCG start
+ //exception for "package ccsid" - it can accept any integer
+ if(index == JDProperties.PACKAGE_CCSID){
+ try{
+ int ccsid = Integer.valueOf(value).intValue();
+ if(ccsid < 1)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ return;
+ }catch(NumberFormatException e){
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ }
+ //Bidi-HCG end
+
+ boolean notValid = true;
+ int current = 0;
+ while (notValid && current < choices.length)
+ {
+ if (value.equalsIgnoreCase(choices[current]))
+ notValid = false;
+ else
+ current++;
+ }
+ if (notValid)
+ throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
+ }
+ }
+
+ /**
+ Serializes the IBM i system and user information.
+ @param out The output stream.
+ @throws IOException If a file I/O error occurs.
+ **/
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ if (!savePasswordWhenSerialized_)
+ {
+ serialPWBytes_ = null;
+ pwHashcode_ = 0;
+
+ serialKeyRingPWBytes_ = null;
+ }
+
+ // Serialize the object.
+ out.defaultWriteObject();
+ }
+
+ /**
+ Returns the string representation of the object.
+ @return The string representation.
+ **/
+ public String toString()
+ {
+ /*
+ Implementation note: Used only for tracing information.
+ */
+ return getDataSourceName();
+ }
+
+ // Twiddle password bytes.
+ // Note: This method generates different output each time it's called against the same password.
+ private static final char[] xpwConfuse(String info)
+ {
+ Random rng = new Random();
+ byte[] adderBytes = new byte[18];
+ rng.nextBytes(adderBytes);
+ char[] adder = BinaryConverter.byteArrayToCharArray(adderBytes);
+
+ byte[] maskBytes = new byte[14];
+ rng.nextBytes(maskBytes);
+ char[] mask = BinaryConverter.byteArrayToCharArray(maskBytes);
+
+ char[] infoBytes = xencode(adder, mask, info.toCharArray());
+ char[] returnBytes = new char[info.length() + 16];
+ System.arraycopy(adder, 0, returnBytes, 0, 9);
+ System.arraycopy(mask, 0, returnBytes, 9, 7);
+ System.arraycopy(infoBytes, 0, returnBytes, 16, info.length());
+
+ return returnBytes;
+ }
+
+ // Get clear password bytes back.
+ private static final String xpwDeconfuse(char[] info)
+ {
+ char[] adder = new char[9];
+ System.arraycopy(info, 0, adder, 0, 9);
+ char[] mask = new char[7];
+ System.arraycopy(info, 9, mask, 0, 7);
+ char[] infoBytes = new char[info.length - 16];
+ System.arraycopy(info, 16, infoBytes, 0, info.length - 16);
+
+ return new String(xdecode(adder, mask, infoBytes));
+ }
+
+ // Scramble some bytes.
+ private static final char[] xencode(char[] adder, char[] mask, char[] bytes)
+ {
+ if (bytes == null) return null;
+ int length = bytes.length;
+ char[] buf = new char[length];
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(bytes[i] + adder[i % 9]);
+ }
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(buf[i] ^ mask[i % 7]);
+ }
+ return buf;
+ }
+
+ private static final char[] xdecode(char[] adder, char[] mask, char[] bytes)
+ {
+ int length = bytes.length;
+ char[] buf = new char[length];
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(mask[i % 7] ^ bytes[i]);
+ }
+ for (int i = 0; i < length; ++i)
+ {
+ buf[i] = (char)(buf[i] - adder[i % 9]);
+ }
+ return buf;
+ }
+
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCManagedDataSource", "javax.sql.DataSource" };
+ }
+
+/* ifdef JDBC40 */
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new SQLFeatureNotSupportedException();
+
+ }
+/* endif */
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCNClob.java b/jdbc40/com/ibm/as400/access/AS400JDBCNClob.java
new file mode 100644
index 000000000..c11805a3f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCNClob.java
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCNClob.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+
+/**
+ * The AS400JDBCNClob class provides access to character large objects. The data
+ * is valid only within the current transaction.
+ */
+
+//@PDA jdbc40 new class
+
+public class AS400JDBCNClob extends AS400JDBCClob
+/* ifdef JDBC40 */
+ implements NClob
+/* endif */
+{
+
+
+ /**
+ * Constructs an AS400JDBCNClob object. The data is contained in the String.
+ * No further communication with the IBM i system is necessary.
+ *
+ * @param data
+ * The NClob data.
+ * @param maxLength
+ * The max length
+ */
+ AS400JDBCNClob(String data, int maxLength)
+ {
+ super(data, maxLength);
+ }
+
+ /**
+ * Constructs an AS400JDBCNClob object. The data is contained in the char array.
+ * No further communication with the IBM i system is necessary.
+ *
+ * @param data
+ * The NClob data.
+ */
+ AS400JDBCNClob(char[] data)
+ {
+ super(data);
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCNClobLocator.java b/jdbc40/com/ibm/as400/access/AS400JDBCNClobLocator.java
new file mode 100644
index 000000000..3fe81cde4
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCNClobLocator.java
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCNClobLocator.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+
+//@PDA jdbc40 new class
+
+
+public class AS400JDBCNClobLocator extends AS400JDBCClobLocator
+/* ifdef JDBC40 */
+implements NClob
+/* endif */
+{
+
+ /**
+ Constructs an AS400JDBCNClobLocator 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.
+ @param savedObject The input savedOjbect.
+ @param savedScale The saved scale.
+ **/
+ AS400JDBCNClobLocator(JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale)
+ {
+ super(locator, converter, savedObject, savedScale);
+ }
+
+ //@xml4 new constructor
+ /**
+ Constructs an AS400JDBCNClobLocator 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 column 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 The input savedOjbect.
+ @param savedScale The saved scale.
+ @param isXML Flag that stream is from an XML column type (needed to strip xml declaration)
+ **/
+ AS400JDBCNClobLocator(JDLobLocator locator, ConvTable converter, Object savedObject, int savedScale, boolean isXML)
+ {
+ super(locator, converter, savedObject, savedScale, isXML);
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCParameterMetaData.java b/jdbc40/com/ibm/as400/access/AS400JDBCParameterMetaData.java
new file mode 100644
index 000000000..fec7d3893
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCParameterMetaData.java
@@ -0,0 +1,207 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCParameterMetaData.java
+//
+// The source code contained herein is licensed under the IBM Public License
+// Version 1.0, which has been approved by the Open Source Initiative.
+// Copyright (C) 1997-2010 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
+
+
+/**
+The AS400JDBCParameterMetaData class can be used to retrieve information about the parameters
+of a PreparedStatement.
+
+Use PreparedStatement.getParameterMetaData() to create new ParameterMetaData objects.
+**/
+public class AS400JDBCParameterMetaData
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+ implements ParameterMetaData
+{
+ final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+
+ // Private data.
+ private AS400JDBCPreparedStatement prepStmt_;
+
+
+
+ /**
+ Constructs an AS400JDBCParameterMetaData object.
+ **/
+ AS400JDBCParameterMetaData (AS400JDBCPreparedStatement prepStmt)
+ {
+ prepStmt_ = prepStmt;
+ }
+
+
+
+ /**
+ Returns the fully-qualified name of the Java class of the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The fully-qualified name of the Java class.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public String getParameterClassName (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getParameterClassName(parameterIndex);
+ }
+
+
+
+ /**
+ Returns the number of parameters in this ParameterMetaData object.
+
+ @return The number of parameters in the ParameterMetaData object.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int getParameterCount ()
+ throws SQLException
+ {
+ return prepStmt_.getParameterCount();
+ }
+
+
+
+ /**
+ Returns the mode of the specified parameter or if that information is unknown.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The mode of the parameter. Valid values are
+ ParameterMetaData.parameterModeIn,
+ ParameterMetaData.parameterModeOut,
+ ParameterMetaData.parameterModeInOut, and
+ ParameterMetaData.parameterModeUnknown.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int getParameterMode (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getParameterMode(parameterIndex);
+ }
+
+
+
+ /**
+ Returns the SQL type of the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The SQL type of the parameter.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int getParameterType (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getParameterType(parameterIndex);
+ }
+
+
+
+ /**
+ Returns the database-specific type name of the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The type name of the parameter.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public String getParameterTypeName (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getParameterTypeName(parameterIndex);
+ }
+
+
+
+ /**
+ Returns the number of decimal digits of the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The precision of the parameter.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int getPrecision (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getPrecision(parameterIndex);
+ }
+
+
+
+ /**
+ Returns the number of digits to the right of the decimal point
+ of the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return The scale of the parameter.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int getScale (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.getScale(parameterIndex);
+ }
+
+
+
+ /**
+ Returns if the specified parameter can be null or that information is unknown.
+
+ @param parameterIndex The parameter index (1-based).
+ @return Returns if the parameter can be null. The valid values are
+ ParameterMetaData.parameterNoNulls,
+ ParameterMetaData.parameterNullable, and
+ ParameterMetaData.parameterNullableUnknown.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public int isNullable (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.isNullable(parameterIndex);
+ }
+
+
+
+ /**
+ Returns if values can be signed numbers for the specified parameter.
+
+ @param parameterIndex The parameter index (1-based).
+ @return Returns true if values for the specified parameter
+ can be signed numbers, false otherwise.
+
+ @exception SQLException If the prepared statement is not open.
+ **/
+ public boolean isSigned (int parameterIndex)
+ throws SQLException
+ {
+ return prepStmt_.isSigned(parameterIndex);
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCParameterMetaData", "java.sql.ParameterMetaData" };
+ }
+
+}
+
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCPooledConnection.java b/jdbc40/com/ibm/as400/access/AS400JDBCPooledConnection.java
new file mode 100644
index 000000000..0ee42f4ed
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCPooledConnection.java
@@ -0,0 +1,471 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCPooledConnection.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-2003 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.ConnectionEventListener;
+import javax.sql.PooledConnection;
+/* ifdef JDBC40 */
+import javax.sql.StatementEventListener;
+/* endif */
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.lang.ref.SoftReference;
+
+/**
+* The AS400JDBCPooledConnection class represents a connection object
+* that provides hooks for connection pool management. This object is returned
+* by the {@link com.ibm.as400.access.AS400JDBCConnectionPoolDataSource#getPooledConnection AS400JDBCConnectionPoolDataSource.getPooledConnection()} method.
+*
+* The following example creates an AS400JDBCPooledConnection object that can be used to cache JDBC connections.
+*
+*
+*
+*
+* // Create a data source for making the connection.
+* AS400JDBCConnectionPoolDataSource dataSource = new AS400JDBCConnectionPoolDataSource("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 connection handle.
+*
+* // Close the connection handle to make available for reuse (physical connection not closed).
+* connection.close();
+*
+* // Reuse the connection somewhere else.
+* Connection reusedConnection = pooledConnection.getConnection();
+* ... work with the connection handle.
+* reusedConnection.close();
+*
+* // Close the physical connection.
+* pooledConnection.close();
+*
+*
+**/
+public class AS400JDBCPooledConnection implements PooledConnection
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+ private AS400JDBCConnection connection_; // The database connection.
+//@CRS - If we maintain a [direct] reference to the handle, and the user doesn't call close(), it
+// will never get closed because it will never get garbage collected.
+// Instead, we are a listener to the handle, so we know when either the user or the
+// garbage collector closes it. At that point, this PooledConnection is no longer
+// considered "in use" and can hand out a new handle when someone calls getConnection().
+
+//@pda (bug reported) 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.
+// After we are done with handle_, we must set it to null, so AS400JDBCConnectionHandle can be GCed.
+// In order for the handle to be GCed, a leaked connection has to be Expired and have handle_ set to null
+// upon returning to available queue.
+ private SoftReference handle_; // The handle to the connection. //@pdc make use of reference to handle
+ // This is a soft reference to an AS400JDBCConnectionHandle object.
+ // DESIGN NOTE:
+ // We use a soft reference (rather than a direct reference) in order to avoid
+ // having circular/mutual direct references between the handle and the connection.
+ // In some scenarios, such circular references can prevent such pairs of objects
+ // from being garbage-collected; which can result in memory leaks.
+ // Advantage of a soft reference: If the connection requester gives up their
+ // reference to the handle but neglects to call close() first,
+ // then the only remaining reference to the handle is the soft reference
+ // from the associated AS400JDBCPooledConnection.
+ // The garbage collector will then notice that the only reference to the handle
+ // is a soft reference; and the GC will then collect/remove the handle.
+
+ private PoolItemProperties properties_; // The usage properties.
+ private AS400JDBCConnectionEventSupport eventManager_;
+
+ private int hashCode_; //@CPMa
+
+ // The following fields are reserved for use by JDConnectionPoolManager. //@CPMa
+ JDConnectionPoolKey poolKey_; // connection-pool key for this connection
+ long timeWhenCreated_; // time when this connection was created.
+ long timeWhenPoolStatusLastModified_; // time when this connection's pooling status last changed.
+ boolean fatalConnectionErrorOccurred_; // this clues the pool manager not to reuse connection
+
+
+ /**
+ * Constructs an AS400JDBCPooledConnection object.
+ * @param connection The physical connection to be pooled.
+ * @exception SQLException If a database error occurs.
+ **/
+ AS400JDBCPooledConnection(Connection connection) throws SQLException
+ {
+ if (connection == null) throw new NullPointerException("connection");
+ connection_ = (AS400JDBCConnection)connection;
+
+ properties_ = new PoolItemProperties();
+ eventManager_ = new AS400JDBCConnectionEventSupport();
+ hashCode_ = connection_.hashCode();
+ timeWhenCreated_ = System.currentTimeMillis();
+
+ if (JDTrace.isTraceOn()) //@G2A
+ {
+ JDTrace.logInformation(this, "A new AS400JDBCPooledConnection was created"); //@G2A
+ }
+ }
+
+
+ /**
+ * Adds a ConnectionEventListener.
+ * @param listener The listener.
+ **/
+ public void addConnectionEventListener(ConnectionEventListener listener)
+ {
+ eventManager_.addConnectionEventListener(listener);
+ }
+
+
+ /**
+ * Closes the physical connection.
+ * @exception SQLException If an error occurs closing the connection.
+ **/
+ public synchronized void close() throws SQLException
+ {
+ if (connection_.isClosed()) return;
+ // Note: AS400JDBCConnectionHandle.close() calls fireConnectionCloseEvent().
+
+ connection_.close(); // close the physical connection
+
+ // Reset the usage timers.
+ properties_.clear();
+
+ if (JDTrace.isTraceOn())
+ { //@G2C
+ JDTrace.logInformation(this, "close() was called on this AS400JDBCPooledConnection"); //@G2C
+ }
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ * Closes all the Statement objects that have been opened by this PooledConnection
+ * object. This method is not supported.
+ * @exception SQLException Always thrown because this method is not supported.
+ **/
+ public void closeAll() throws SQLException
+ {
+ JDError.throwSQLException(JDError.EXC_FUNCTION_NOT_SUPPORTED);
+ }
+
+
+ // JDConnectionPoolManager needs this when identifying returned connections.
+ public boolean equals(Object obj)
+ {
+ if (obj == null) return false;
+ try
+ {
+ AS400JDBCPooledConnection pc = (AS400JDBCPooledConnection)obj;
+ return (connection_.equals(pc.connection_));
+ }
+ catch (Throwable e) {
+ return false;
+ }
+ }
+
+ // Needed for good hashing.
+ public int hashCode()
+ {
+ return hashCode_;
+ }
+
+
+ // Note: The following method is called by AS400JDBCConnectionHandle.close().
+ /**
+ * Fire the connection closed event.
+ * @param event The ConnectionEvent.
+ **/
+ void fireConnectionCloseEvent(ConnectionEvent event)
+ {
+ returned(); // Reset the pooledConnection.
+ eventManager_.fireCloseEvent(event); // Notify the pool.
+ }
+
+
+ // Note: The following method is called by AS400JDBCConnectionHandle.close().
+ /**
+ * Fire the connection error event.
+ * @param event The ConnectionEvent.
+ **/
+ void fireConnectionErrorEvent(ConnectionEvent event)
+ {
+ // Don't bother cleaning up the connection, it won't get re-used.
+ eventManager_.fireErrorEvent(event); // Notify the pool.
+ }
+
+ /**
+ * Returns the connection handle to the database. Only one connection handle can be open
+ * at a time for any given AS400JDBCPooledConnection object.
+ * @return The connection handle.
+ * @exception SQLException If a database error occurs or if this PooledConnection is already in use.
+ **/
+ public synchronized Connection getConnection() throws SQLException
+ {
+ if (JDTrace.isTraceOn()) //@G2C
+ {
+ JDTrace.logInformation(this, "AS400JDBCPooledConnection.getConnection() was called"); //@G2C
+ }
+ return getConnectionHandle();
+ }
+
+
+ // Used by JDConnectionPoolManager. //@CPMa
+ /**
+ * Returns the connection handle to the database. Only one connection handle can be open
+ * at a time for any given AS400JDBCPooledConnection object.
+ * @return The connection handle.
+ * @exception SQLException If a database error occurs or if this PooledConnection is already in use.
+ **/
+ synchronized final AS400JDBCConnectionHandle getConnectionHandle() throws SQLException
+ {
+ if (connection_.isClosed())
+ {
+ if (JDTrace.isTraceOn()) // @G2A
+ {
+ JDTrace.logInformation(this, "This AS400JDBCPooledConnection is invalid because connection is closed."); // @G2A
+ }
+ JDError.throwSQLException(this, JDError.EXC_CONNECTION_NONE); //@G2A
+ }
+
+ // Note: The JDBC Tutorial says that if PooledConnection.getConnection() is called while already in use, this should close the existing connection. "The purpose of allowing the server to invoke the method getConnection a 2nd time is to give the application server a way to take a connection away from an application and give it to someone else. This will probably rarely happen, but the capability is there."
+ // However, we haven't had a request for this behavior, so we just throw an exception instead.
+ if (isInUse())
+ {
+ if (JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation(this, "This AS400JDBCPooledConnection is already in use.");
+ }
+ JDError.throwSQLException(this, JDError.EXC_CONNECTION_UNABLE); // Is this the right thing to throw here?
+ }
+
+ // Start the connection tracking timers.
+ setInUse(true);
+
+ AS400JDBCConnectionHandle handle = new AS400JDBCConnectionHandle(this, connection_); //@pdc handle
+ handle_ = new SoftReference(handle);
+ return handle; //@pda handle
+ }
+
+
+ // For exclusive use by JDConnectionPoolManager. //@CPMa
+ final JDConnectionPoolKey getPoolKey()
+ {
+ return poolKey_;
+ }
+
+
+ AS400JDBCConnection getInternalConnection() //@G1A
+ { //@G1A
+ return connection_; //@G1A
+ } //@G1A
+
+
+ /**
+ * Returns the elapsed time the connection has been idle waiting in the pool.
+ * @return The idle time (milliseconds).
+ **/
+ public long getInactivityTime()
+ {
+ return properties_.getInactivityTime();
+ }
+
+
+ /**
+ * Returns the elapsed time the connection has been in use.
+ * @return The elapsed time (milliseconds).
+ **/
+ public long getInUseTime()
+ {
+ return properties_.getInUseTime();
+ }
+
+
+ /**
+ * Returns the elapsed time the pooled connection has been alive.
+ * @return The elapsed time (milliseconds).
+ **/
+ public long getLifeSpan()
+ {
+ return properties_.getLifeSpan();
+ }
+
+
+ /**
+ * Returns the number of times the pooled connection has been used.
+ * @return The number of times used.
+ **/
+ public int getUseCount()
+ {
+ return properties_.getUseCount();
+ }
+
+
+ /**
+ * Ping the connection to check the status.
+ * @return true if the connection is active; false otherwise.
+ **/
+ boolean isConnected() throws SQLException // @A3A
+ {
+ return connection_.getAS400().isConnected(AS400.DATABASE);
+ }
+
+
+ /**
+ * Determine whether the connection is still alive.
+ * @return true if the connection is alive; false otherwise.
+ **/
+ boolean isConnectionAlive() throws SQLException
+ {
+ return connection_.getAS400().isConnectionAlive(AS400.DATABASE);
+ }
+
+
+ /**
+ * Indicates if the pooled connection is in use.
+ * @return true if the pooled connection is in use; false otherwise.
+ **/
+ public boolean isInUse()
+ {
+ return properties_.isInUse();
+ }
+
+
+ /**
+ * Removes a ConnectionEventListener.
+ * @param listener The listener to be removed.
+ **/
+ public void removeConnectionEventListener(ConnectionEventListener listener)
+ {
+ eventManager_.removeConnectionEventListener(listener);
+ }
+
+
+ /**
+ * Returns the connection after usage.
+ * Update the connection timers and invalidate connection handle.
+ **/
+ synchronized void returned()
+ {
+ if (JDTrace.isTraceOn()) //@G2C
+ {
+ JDTrace.logInformation(this, "This AS400JDBCPooledConnection is being returned."); //@G2C
+ }
+
+ // Reset the timers.
+ setInUse(false);
+
+ try { //@CPMa
+ connection_.clearWarnings(); // This seems safe and reasonable enough.
+ connection_.setHoldability(AS400JDBCResultSet.HOLDABILITY_NOT_SPECIFIED); // This is the default for all new instances of AS400JDBCConnection.
+ boolean readOnly = connection_.isReadOnlyAccordingToProperties(); // Get default from props.
+ connection_.setReadOnly(readOnly); // In case the user forgot to reset.
+ connection_.setAutoCommit(true); // Ditto.
+ if (handle_ != null) //@pda handle
+ {
+ AS400JDBCConnectionHandle handle = (AS400JDBCConnectionHandle)handle_.get();
+ if (handle != null)
+ {
+ handle.invalidate(); //@pda Invalidate the handle.
+ // So if this pooledConnection gets expired then also need to invalidate handle (remove reference from handle to pooledConnection).
+ //if the handle gets GCed (due to connection leak), then handle.finalize() will not try to close this pooledConnection, which could have been already assigned to a new handle.
+ //(ie prevent two handles from pointing to one pooledConnection)
+ }
+ handle_ = null; //remove reference also, so handle is free for GC.
+ }
+ }
+ catch (SQLException e) {
+ JDTrace.logException(this, "Exception while resetting properties of returned connection.", e);
+ }
+
+ // Note: We can assume that if the connection has been used and then returned to the pool, it has been sufficiently cleaned-up/reset by AS400JDBCConnectionHandle.close(), which calls AS400JDBCConnection.pseudoClose(), which does any needed rollbacks and/or statement closing. //@CPMa
+ }
+
+
+ /**
+ * Sets the connection timer values based on the active usage state of the connection.
+ * @param inUse true if the connection is currently active; false otherwise.
+ **/
+ synchronized void setInUse(boolean inUse)
+ {
+ properties_.setInUse(inUse);
+ }
+
+
+ // For exclusive use by JDConnectionPoolManager. //@CPMa
+ final void setPoolKey(JDConnectionPoolKey key)
+ {
+ poolKey_ = key;
+ }
+
+ //@PDA jdbc40
+ /**
+ * Registers a
+*
+* StatementEventListener
with this PooledConnection
object. Components that
+ * wish to be notified when PreparedStatement
s created by the
+ * connection are closed or are detected to be invalid may use this method
+ * to register a StatementEventListener
with this PooledConnection
object.
+ * StatementEventListener
+ * interface that is to be registered with this PooledConnection
object
+ */
+/* ifdef JDBC40 */
+ public void addStatementEventListener(StatementEventListener listener)
+ {
+ //Currently toolbox does not have a pooledStatemnt.
+
+ //Method can not throw SQLException in current driver
+ //For now just do nothing in this method.
+ if (JDTrace.isTraceOn()) //@G2C
+ {
+ JDTrace.logInformation(this, "AS400JDBCPooledConnection.addStatementEventListener is called, but is N/A.");
+ }
+ }
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ * Removes the specified StatementEventListener
from the list of
+ * components that will be notified when the driver detects that a
+ * PreparedStatement
has been closed or is invalid.
+ * StatementEventListener
interface that was previously
+ * registered with this PooledConnection
object
+ */
+/* ifdef JDBC40 */
+ public void removeStatementEventListener(StatementEventListener listener)
+ {
+ //Method can not throw SQLException
+ //For now just do nothing
+ if (JDTrace.isTraceOn()) //@G2C
+ {
+ JDTrace.logInformation(this, "AS400JDBCPooledConnection.removeStatementEventListener is called, but is N/A.");
+ }
+ }
+/* endif */
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCPreparedStatement.java b/jdbc40/com/ibm/as400/access/AS400JDBCPreparedStatement.java
new file mode 100644
index 000000000..ac8014edc
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCPreparedStatement.java
@@ -0,0 +1,4689 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCPreparedStatement.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.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.BatchUpdateException;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.DataTruncation;
+import java.sql.Date;
+/* ifdef JDBC40 */
+ import java.sql.NClob;
+/* endif */
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+/* ifdef JDBC40 */
+ import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+ import java.sql.SQLXML;
+/* endif */
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ *
+ * PreparedStatement ps = connection
+ * .prepareStatement("INSERT INTO COLLECTION.TABLE VALUES(?)");
+ * ResultSetMetaData rsmd = ps.getMetaData();
+ *
+ *
+ * @return The metadata object, or null if the statement does not return a
+ * result set.
+ * @exception SQLException
+ * If the statement is not open.
+ **/
+ public ResultSetMetaData getMetaData() throws SQLException {
+ synchronized (internalLock_) { // @F1A
+ checkOpen();
+
+ if (resultRow_ == null) // @H6a
+ return null; // @H6a
+
+ ConvTable convTable = null; // @G6A
+ DBExtendedColumnDescriptors extendedDescriptors = getExtendedColumnDescriptors(); // @G6A
+ // If we have extendedDescriptors, send a ConvTable to convert them, else
+ // pass null // @G6A
+ if (extendedDescriptors != null) // @G6A
+ {
+ // @G6A
+ convTable = ((AS400JDBCConnection) connection_).converter_; // @G6A
+ } // @G6A
+ return new AS400JDBCResultSetMetaData(connection_.getCatalog(),
+ resultSetConcurrency_, cursor_.getName(), resultRow_,
+ extendedDescriptors, convTable, connection_); // @in1 // @G6A
+ }
+ }
+
+ // @G4A
+ // Return the class name of a parameter for ParameterMetaData support.
+ String getParameterClassName(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.getJavaClassName(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).getJavaClassName();
+ }
+ }
+
+ // @G4A
+ // Return the parameter count for ParameterMetaData support.
+ int getParameterCount() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+ if (useReturnValueParameter_) {
+ return parameterCount_ + 1;
+ }
+ return parameterCount_;
+ }
+ }
+
+ // @G4A JDBC 3.0
+ /**
+ * Returns the number, types, and properties of a PreparedStatement object's
+ * parameters.
+ *
+ * @return The ParameterMetaData object that describes this prepared statement
+ * object.
+ * @exception SQLException
+ * If the statement is not open.
+ * @since Modification 5
+ **/
+ public ParameterMetaData getParameterMetaData() throws SQLException {
+ synchronized (internalLock_) {
+ checkOpen();
+ return (ParameterMetaData) (Object) new AS400JDBCParameterMetaData(this);
+ }
+ }
+
+ // @G4A
+ // Return the mode of a parameter for ParameterMetaData support.
+ int getParameterMode(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return ParameterMetaData.parameterModeOut; // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ boolean input = parameterRow_.isInput(param);
+ boolean output = parameterRow_.isOutput(param);
+
+ if (input && output) {
+ return ParameterMetaData.parameterModeInOut;
+ } else if (input) {
+ return ParameterMetaData.parameterModeIn;
+ } else if (output) {
+ return ParameterMetaData.parameterModeOut;
+ } else
+ return ParameterMetaData.parameterModeUnknown;
+ }
+ }
+
+ // @G4A
+ // Return the type of a parameter for ParameterMetaData support.
+ int getParameterType(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.getType(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).getType();
+ }
+ }
+
+ // @G4A
+ // Return the type name of a parameter for ParameterMetaData support.
+ String getParameterTypeName(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.getTypeName(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).getTypeName();
+ }
+ }
+
+ // @G4A
+ // Return the precision of a parameter for ParameterMetaData support.
+ int getPrecision(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.getPrecision(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).getPrecision();
+ }
+ }
+
+ // @G4A
+ // Return the scale of a parameter for ParameterMetaData support.
+ int getScale(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.getScale(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).getScale();
+ }
+ }
+
+ // @G4A
+ // Return whether a parameter is nullable for ParameterMetaData support.
+ int isNullable(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return ResultSetMetaData.columnNoNulls; // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.isNullable(param);
+ }
+ }
+
+ // @G4A
+ // Return whether a parameter is signed for ParameterMetaData support.
+ boolean isSigned(int param) throws SQLException {
+ if (param > getParameterCount() || param < 1) {
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+ }
+ synchronized (internalLock_) {
+ checkOpen();
+
+ if (useReturnValueParameter_) // @G8a
+ {
+ // @G8a
+ if (param == 1) // @G8a
+ return returnValueParameter_.isSigned(); // @G8a
+ else
+ // @G8a
+ param--; // @G8a
+ } // @G8a
+
+ return parameterRow_.getSQLData(param).isSigned();
+ }
+ }
+
+ // JDBC 2.0
+ /**
+ * Sets an input parameter to an Array value. DB2 for IBM i only supports
+ * arrays in stored procedures.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * Always thrown because DB2 for IBM i does not support arrays.
+ **/
+ public void setArray(int parameterIndex, Array parameterValue)
+ throws SQLException {
+ // @array new support
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setArray()");
+ if (parameterValue == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: Array type " + parameterValue.getBaseTypeName());
+ }
+
+ if (!sqlStatement_.isProcedureCall()) // @array
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID); // @array
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ /**
+ * 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 parameterIndex
+ * The parameter index (1-based).
+ * @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(int parameterIndex, InputStream parameterValue,
+ int length) throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setAsciiStream()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length); // @H1A
+ } // @H1A
+
+ // Validate the length parameter
+ if (length < 0)
+ JDError.throwSQLException(this, JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (parameterValue != null) {
+
+ try {
+ // If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (sqlType == SQLData.CLOB_LOCATOR
+ || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR || // @pdc jdbc40
+/* ifdef JDBC40 */
+ sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
+/* endif */
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ sqlData.set(new ConvTableReader(parameterValue, 819, 0,
+ LOB_BLOCK_SIZE), null, length); // @J0M hacked this to use the
+ // scale parm for the length
+ } else {
+ sqlData.set(JDUtilities.readerToString(new ConvTableReader(
+ parameterValue, 819, 0, LOB_BLOCK_SIZE), length), null, -1);
+ }
+ } catch (UnsupportedEncodingException uee) {
+ /* do nothing */
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (parameterValue == null);
+ parameterDefaults_[parameterIndex - 1] = false; // @EIA
+ parameterUnassigned_[parameterIndex - 1] = false; // @EIA
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+
+ // @J0M setValue (parameterIndex,
+ // @J0M (parameterValue == null) ? null : JDUtilities.streamToString
+ // (parameterValue, length, "ISO8859_1"), // @B2C
+ // @J0M null, -1); //@P0C
+ }
+
+ /**
+ * Sets an input parameter to a BigDecimal value. The driver converts this to
+ * an SQL NUMERIC value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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(int parameterIndex, BigDecimal parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setBigDecimal()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ /**
+ * 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.
+ *
+ *
+ * If a parameter is set using setBinaryStream, then the parameter must be
+ * reset prior to the second execute of the PreparedStatement object.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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(int parameterIndex, InputStream parameterValue,
+ int length) throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setBinaryStream()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length); // @H1A
+ } // @H1A
+
+ // Validate the length parameter
+ if (length < 0)
+ JDError.throwSQLException(this, JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) // @KKC Removed comment brace
+ {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If it's not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() will throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (parameterValue != null) {
+ // If the data is a locator, then set its handle.
+ if (sqlData instanceof SQLLocator) {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ // Don't convert immediately to Bytes. This causes memory problems
+ // with Large lobs @B3A
+ // sqlData.set (JDUtilities.streamToBytes(parameterValue, length),
+ // null, length);//@set1 allow setX one time and reuse execute()
+ // without having to reset stream
+ sqlData.set(parameterValue, null, length); // @J0M hacked this to use
+ // the scale parm for the
+ // length
+
+ } else {
+ sqlData.set(JDUtilities.streamToBytes(parameterValue, length), null,
+ length);
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (parameterValue == null);
+ parameterDefaults_[parameterIndex - 1] = false; // @EIA
+ parameterUnassigned_[parameterIndex - 1] = false; // @EIA
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+ // @KKC */
+ // @KKC setValue(parameterIndex, parameterValue, null, length);
+ // @J0D setValue (parameterIndex,
+ // @J0D (parameterValue == null) ? null : JDUtilities.streamToBytes
+ // (parameterValue, length), // @B2C
+ // @J0D null, -1);
+ }
+
+ // JDBC 2.0
+ /**
+ * Sets an input parameter to a Blob value. The driver converts this to an SQL
+ * BLOB value.
+ * If proxy support is in use, the Blob must be serializable.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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, or the parameter is not
+ * serializable (when proxy support is in use).
+ **/
+ public void setBlob(int parameterIndex, Blob parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setBlob()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + parameterValue.length()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a Java boolean value. The driver converts this
+ * to an SQL SMALLINT value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index 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(int parameterIndex, boolean parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setBoolean()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Short((short) (parameterValue ? 1 : 0)), null,
+ -1);
+ }
+
+ /**
+ * Sets an input parameter to a Java byte value. The driver converts this to
+ * an SQL SMALLINT value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index 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(int parameterIndex, byte parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setByte()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Short(parameterValue), null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a Java byte array value. The driver converts
+ * this to an SQL VARBINARY value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 setBytes(int parameterIndex, byte[] parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setBytes()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else if (parameterValue.length > maxToLog_)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + parameterValue.length); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + parameterValue.length + " value: "
+ + new String(parameterValue)); // @H1A //@PDC
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ // JDBC 2.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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @param length
+ * The number of characters to read from 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(int parameterIndex, Reader parameterValue,
+ int length) throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setCharacterStream()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length); // @H1A
+ } // @H1A
+
+ // Validate length parameter
+ if (length < 0)
+ JDError.throwSQLException(this, JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (parameterValue != null) {
+
+ // If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (sqlType == SQLData.CLOB_LOCATOR || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR || // @pdc jdbc40
+ sqlType == SQLData.NCLOB_LOCATOR || // @pda jdbc40
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ // @pddsqlData.set(parameterValue, null, length); // @J0M hacked this
+ // to use the scale parameter for the length
+ sqlData.set(JDUtilities.readerToString(parameterValue, length), null,
+ -1); // @pdc length is incorrect for double-byte chars. Use a
+ // slower, but correct method, until we can create a real
+ // ConvTableReader
+ } else {
+ sqlData.set(JDUtilities.readerToString(parameterValue, length), null,
+ -1);
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (parameterValue == null);
+ parameterDefaults_[parameterIndex - 1] = false; // @EIA
+ parameterUnassigned_[parameterIndex - 1] = false; // @EIA
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+
+ // @J0D setValue (parameterIndex,
+ // @J0D (parameterValue == null) ? null : JDUtilities.readerToString
+ // (parameterValue, length), // @B2C
+ // @J0D null, -1); //@P0C
+ }
+
+ // JDBC 2.0
+ /**
+ * Sets an input parameter to a Clob value. The driver converts this to an SQL
+ * CLOB value.
+ * If proxy support is in use, the Clob must be serializable.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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, or the parameter is not
+ * serializable (when proxy support is in use).
+ **/
+ public void setClob(int parameterIndex, Clob parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setClob()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else if (parameterValue.length() > maxToLog_) // @H1A
+ JDTrace
+ .logInformation(
+ this,
+ "parameter index: "
+ + parameterIndex
+ + " value: "
+ + parameterValue.getSubString(1,
+ (int) parameterValue.length())); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + parameterValue.length()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a java.sql.Date value using the default
+ * calendar. The driver converts this to an SQL DATE value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 setDate(int parameterIndex, Date parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setDate()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1); // @P0C
+ }
+
+ // JDBC 2.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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @param calendar
+ * 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(int parameterIndex, Date parameterValue, Calendar calendar)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setDate()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ if (calendar == null)
+ JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ setValue(parameterIndex, parameterValue, calendar, -1);
+ }
+
+ // @EIA 550 extended indicator defaults
+ /**
+ * Sets an input parameter to the default value
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @exception SQLException
+ * If the statement is not open, the index is not valid, the
+ * parameter is not an input parameter.
+ **/
+ public void setDB2Default(int parameterIndex) throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setDB2Default()");
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex);
+ }
+
+ setValueExtendedIndicator(parameterIndex, 1); // 1 is default
+
+ }
+
+ // @EIA 550 extended indicator defaults
+ /**
+ * Sets an input parameter to the default value. This is a the same as
+ * setDB2Default.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @exception SQLException
+ * If the statement is not open, the index is not valid, the
+ * parameter is not an input parameter.
+ **/
+ public void setDBDefault(int parameterIndex) throws SQLException {
+ setDB2Default(parameterIndex);
+ }
+
+ // @EIA 550 extended indicator defaults
+ /**
+ * Sets an input parameter to unassigned
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @exception SQLException
+ * If the statement is not open, the index is not valid, the
+ * parameter is not an input parameter.
+ **/
+ public void setDB2Unassigned(int parameterIndex) throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setDB2Unassigned()");
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex);
+ }
+
+ setValueExtendedIndicator(parameterIndex, 2); // 2 is unassigned
+
+ }
+
+ // @EIA 550 extended indicator defaults
+ /**
+ * Sets an input parameter to unassigned. This is a the same as
+ * setDB2Unassigned.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @exception SQLException
+ * If the statement is not open, the index is not valid, the
+ * parameter is not an input parameter.
+ **/
+ public void setDBUnassigned(int parameterIndex) throws SQLException {
+ setDB2Unassigned(parameterIndex); // 2 is unassigned
+ }
+
+ /**
+ * Sets an input parameter to a Java double value. The driver converts this to
+ * an SQL DOUBLE value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index is not valid or the
+ * parameter is not an input parameter.
+ **/
+ public void setDouble(int parameterIndex, double parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setDouble()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Double(parameterValue), null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a Java float value. The driver converts this to
+ * an SQL REAL value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index 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 symmetrical and certain INOUT
+ // parameters do not work.
+ //
+ public void setFloat(int parameterIndex, float parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setFloat()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Float(parameterValue), null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a Java int value. The driver converts this to an
+ * SQL INTEGER value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index is not valid or the
+ * parameter is not an input parameter.
+ **/
+ public void setInt(int parameterIndex, int parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setInt()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Integer(parameterValue), null, -1);
+ }
+
+ // @D0C
+ /**
+ * 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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index 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(int parameterIndex, long parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setLong()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Long(parameterValue), null, -1); // @D0C
+ }
+
+ /**
+ * Sets an input parameter to SQL NULL.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param sqlType
+ * 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, or the SQL type is not
+ * valid.
+ **/
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+ // @BBD if (sqlType != parameterRow_.getSQLData (parameterIndex).getType ())
+ // @BBD JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // @D8 ignore the type supplied by the user. We are checking it
+ // only to rigidly follow the JDBC spec. Ignoring the type
+ // will make us a friendlier driver.
+ //
+ // @D8d testSQLType(sqlType, parameterIndex); // @BBA
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setNull()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, null, null, -1);
+ }
+
+ // @B4 - Added for JDK 2.0RC1 - typeName can be ignored, since it is not
+ // relevant to IBM i.
+ /**
+ * Sets an input parameter to SQL NULL.
+ *
+ * @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 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(int parameterIndex, int sqlType, String typeName)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setNull()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ } // @H1A
+
+ setNull(parameterIndex, sqlType);
+ }
+
+ /**
+ * 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 parameterIndex
+ * The parameter index (1-based).
+ * @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(int parameterIndex, Object parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setObject()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " type: " + parameterValue.getClass().getName() + " toString():"
+ + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1); // @P0C
+ }
+
+ /**
+ * 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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @param sqlType
+ * 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, or the parameter is not serializable (when proxy
+ * support is in use).
+ **/
+ public void setObject(int parameterIndex, Object parameterValue, int sqlType)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // @BBD if (sqlType != parameterRow_.getSQLData (parameterIndex).getType ())
+ // @BBD JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // @D8 ignore the type supplied by the user. We are checking it
+ // only to rigidly follow the JDBC spec. Ignoring the type
+ // will make us a friendlier driver.
+ //
+ // @D8d testSQLType(sqlType, parameterIndex); // @BBA
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setObject()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " type: " + parameterValue.getClass().getName() + " toString():"
+ + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1); // @P0C
+ }
+
+ /**
+ * 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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @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 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(int parameterIndex, Object parameterValue, int sqlType,
+ int scale) throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // @BBD if (sqlType != parameterRow_.getSQLData (parameterIndex).getType ())
+ // @BBD JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // @D8 ignore the type supplied by the user. We are checking it
+ // only to rigidly follow the JDBC spec. Ignoring the type
+ // will make us a friendlier driver.
+ //
+ // @D8d testSQLType(sqlType, parameterIndex); // @BBA
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setObject()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " type: " + parameterValue.getClass().getName() + " toString():"
+ + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ if (scale < 0)
+ JDError.throwSQLException(this, JDError.EXC_SCALE_INVALID);
+/* ifdef JDBC40 */
+ if (parameterValue instanceof SQLXML) //@xmlspec
+ setSQLXML(parameterIndex, (SQLXML)parameterValue); //@xmlspec
+ else
+/* endif */
+
+ setValue(parameterIndex, parameterValue, null, scale); // @P0C
+ }
+
+ // JDBC 2.0
+ /**
+ Sets an input parameter to a Ref value. DB2 for IBM i
+ does not support structured types.
+
+ @param parameterIndex The parameter index (1-based).
+ @param parameterValue The parameter value.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support structured types.
+ **/
+ public void setRef(int parameterIndex, Ref parameterValue)
+ throws SQLException {
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ }
+
+ /**
+ * Sets an input parameter to a Java short value. The driver converts this to
+ * an SQL SMALLINT value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value.
+ * @exception SQLException
+ * If the statement is not open, the index is not valid or the
+ * parameter is not an input parameter.
+ **/
+ public void setShort(int parameterIndex, short parameterValue)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setShort()"); // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, new Short(parameterValue), null, -1);
+ }
+
+ /**
+ * Sets an input parameter to a String value. The driver converts this to an
+ * SQL VARCHAR value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 setString(int parameterIndex, String parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setString()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else if (parameterValue.length() > maxToLog_) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + parameterValue.length()); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue); // @H1A
+ } // @H1A
+ // if(parameterIndex <= parameterCount_ && parameterIndex > 0) //@pdc
+ // parameterValue =
+ // AS400BidiTransform.convertDataToHostCCSID(parameterValue, connection_,
+ // //Bidi-HCG
+ // parameterRow_.getCCSID (parameterIndex)); //Bidi-HCG
+
+ setValue(parameterIndex, parameterValue, null, -1); // @B7C @P0C
+ }
+
+ /**
+ * Sets an input parameter to a java.sql.Time value using the default
+ * calendar. The driver converts this to an SQL TIME value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 setTime(int parameterIndex, Time parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setTime()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1); // @P0C
+ }
+
+ // JDBC 2.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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @param calendar
+ * 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(int parameterIndex, Time parameterValue, Calendar calendar)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setTime()"); // @H1
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ if (calendar == null)
+ JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ setValue(parameterIndex, parameterValue, calendar, -1);
+ }
+
+ /**
+ * Sets an input parameter to a java.sql.Timestamp value using the default
+ * calendar. The driver converts this to an SQL TIMESTAMP value.
+ *
+ * @param parameterIndex
+ * The parameter index (1-based).
+ * @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 setTimestamp(int parameterIndex, Timestamp parameterValue)
+ throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setTimeStamp()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ setValue(parameterIndex, parameterValue, null, -1); // @P0C
+ }
+
+ // JDBC 2.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 parameterIndex
+ * The parameter index (1-based).
+ * @param parameterValue
+ * The parameter value or null to set the value to SQL NULL.
+ * @param calendar
+ * 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(int parameterIndex, Timestamp parameterValue,
+ Calendar calendar) throws SQLException {
+ // @B2D if (parameterValue == null)
+ // @B2D JDError.throwSQLException (this,
+ // JDError.EXC_PARAMETER_TYPE_INVALID);
+ if (JDTrace.isTraceOn()) { // @H1A
+ JDTrace.logInformation(this, "setTimeStamp()"); // @H1A
+ if (parameterValue == null) // @H1A
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL"); // @H1A
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + parameterValue.toString()); // @H1A
+ } // @H1A
+
+ if (calendar == null)
+ JDError.throwSQLException(this, JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ setValue(parameterIndex, parameterValue, calendar, -1);
+ }
+
+ /**
+ * Sets an input parameter to a Unicode 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.
+ * java.sql.RowId
object. The
+ * driver converts this to a SQL ROWID
value when it sends it
+ * to the database
+ *
+ * @param parameterIndex
+ * @param x the parameter value
+ * @throws SQLException if a database access error occurs
+ *
+ */
+/* ifdef JDBC40 */
+ public void setRowId(int parameterIndex, RowId x) throws SQLException
+ {
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this, "setRowId()");
+ if(x == null)
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: NULL");
+ else
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: " + x.toString());
+ }
+ setValue (parameterIndex, x, null, -1);
+ }
+/* endif */
+ // @PDA jdbc40
+ /**
+ * Sets the designated paramter to the given String
object. The
+ * driver converts this to a SQL NCHAR
or NVARCHAR
+ * or LONGNVARCHAR
value (depending on the argument's size
+ * relative to the driver's limits on NVARCHAR
values) when it
+ * sends it to the database.
+ *
+ * @param parameterIndex
+ * @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 ; or
+ * if a database access error occurs
+ */
+ public void setNString(int parameterIndex, String value) throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setNString()");
+ if (value == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else if (value.length() > maxToLog_)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + value.length());
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: " + value);
+ }
+ setString(parameterIndex, value);
+ }
+
+ // @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 parameterIndex
+ * @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 ; or
+ * if a database access error occurs
+ */
+ public void setNCharacterStream(int parameterIndex, Reader value, long length)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setNCharacterStream()");
+ if (value == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length);
+ }
+ setCharacterStream(parameterIndex, value, (int) length);
+ }
+
+ // @PDA jdbc40
+ /**
+ * Sets the designated parameter to a java.sql.NClob
object. The driver converts this to a
+ * SQL NCLOB
value when it sends it to the database.
+ * @param parameterIndex
+ * @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 ; or if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void setNClob(int parameterIndex, NClob value) throws SQLException
+ {
+
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logInformation (this, "setNClob()");
+ if(value == null)
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: NULL");
+ else if(value.length() > maxToLog_)
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: " + value.getSubString(1, (int)value.length()));
+ else JDTrace.logInformation (this, "parameter index: " + parameterIndex + " length: " + value.length());
+ }
+ setClob(parameterIndex, 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
+ * PreparedStatement
is executed.
+ *
+ * @param parameterIndex
+ * @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, or if the length specified is less than zero.
+ *
+ */
+ public void setClob(int parameterIndex, Reader reader, long length)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setClob()");
+ if (reader == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length);
+ }
+
+ setCharacterStream(parameterIndex, reader, (int) length);
+ }
+
+ // @PDA jdbc40
+ /**
+ * Sets the designated parameter to an InputStream
object. The
+ * inputStream must contain the number of characters specified by length
+ * otherwise a SQLException
will be generated when the
+ * PreparedStatement
is executed.
+ *
+ * @param parameterIndex
+ * @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, if the length specified is less than zero or
+ * if the number of bytes in the inputstream does not match the
+ * specfied length.
+ *
+ */
+ public void setBlob(int parameterIndex, InputStream inputStream, long length)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setBlob()");
+ if (inputStream == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length);
+ }
+ setBinaryStream(parameterIndex, inputStream, (int) length);
+ }
+
+ // @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
+ * PreparedStatement
is executed.
+ *
+ * @param parameterIndex
+ * @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; or if
+ * a database access error occurs
+ *
+ */
+ public void setNClob(int parameterIndex, Reader reader, long length)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setNClob()");
+ if (reader == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ else
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " length: " + length);
+ }
+
+ setCharacterStream(parameterIndex, reader, (int) length);
+ }
+
+ // @PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.SQLXML
object.
+ * @param parameterIndex
+ * @param xmlObject a SQLXML
object that maps an SQL XML
value
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
+ {
+ if(JDTrace.isTraceOn())
+ {
+ int len;
+
+ if(xmlObject == null)
+ len = 0;
+ else
+ len = xmlObject.getString().length(); //no length() method yet in jdbc.
+
+ JDTrace.logInformation (this, "setSQLXML()");
+ if(xmlObject == null)
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: NULL");
+ else if(len < maxToLog_)
+ JDTrace.logInformation (this, "parameter index: " + parameterIndex + " value: " + xmlObject.getString());
+ else JDTrace.logInformation (this, "parameter index: " + parameterIndex + " length: " + len);
+ }
+
+ //@xmlspec special handling of blob/clob column types
+ if(xmlObject == null) //@xmlspec3
+ { //@xmlspec3
+ setValue (parameterIndex, xmlObject, null, -1); //@xmlspec3
+ return; //@xmlspec3
+ } //@xmlspec3
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex); //@xmlspec
+ int sqlDataType = sqlData.getType(); //@xmlspec
+ switch(sqlDataType) { //@xmlspec
+ case Types.CLOB: //@xmlspec
+ setCharacterStream(parameterIndex, xmlObject.getCharacterStream());//@xmlspec
+ break; //@xmlspec
+ case Types.BLOB: //@xmlspec
+ setBinaryStream(parameterIndex, xmlObject.getBinaryStream()); //@xmlspec
+ break; //@xmlspec
+ default: //@xmlspec
+ setValue (parameterIndex, xmlObject, null, -1);
+ }
+ }
+/* endif */
+
+ // @pda jdbc40
+ protected String[] getValidWrappedList() {
+ return new String[] { "com.ibm.as400.access.AS400JDBCPreparedStatement",
+ "java.sql.PreparedStatement" };
+ }
+
+ // @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.
+ *
+ * PreparedStatement
+ */
+ public void setAsciiStream(int parameterIndex, InputStream x, long length)
+ throws SQLException {
+ setAsciiStream(parameterIndex, x, (int) 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.
+ *
+ * PreparedStatement
+ */
+ public void setBinaryStream(int parameterIndex, InputStream x, long length)
+ throws SQLException {
+ setBinaryStream(parameterIndex, x, (int) 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.
+ *
+ * java.io.Reader
object that contains the Unicode
+ * data
+ * @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 PreparedStatement
+ */
+ public void setCharacterStream(int parameterIndex, Reader reader, long length)
+ throws SQLException {
+ setCharacterStream(parameterIndex, reader, (int) length);
+ }
+
+ // @pda jdbc40 needed for rowset.setX methods. Moved from callableStatement.
+ /*
+ * Find the column index that matches this parameter name.
+ *
+ * @param parameterName The parameter name to change into a column index
+ * (1-based).
+ */
+ int findParameterIndex(String parameterName) throws SQLException {
+ // Throw an exception if null was passed in
+ if (parameterName == null) {
+ throw 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_];
+
+ //
+ // Check to see if the parameter names were returned by the super
+ // extended parameter marker format.
+ // This logic added @G5A 8/20/2012
+ //
+ boolean allFound = true;
+ for (int parameterNumber = 0; allFound
+ && parameterNumber < parameterCount_; parameterNumber++) {
+ try {
+ String name = parameterRow_.getFieldName(parameterNumber + 1);
+ if (name != null) {
+ parameterNames_[parameterNumber] = name;
+ if (caseSensitive && name.equals(parameterName))
+ returnParm = parameterNumber + 1;
+ else if (!caseSensitive && name.equalsIgnoreCase(parameterName))
+ returnParm = parameterNumber + 1;
+ } else {
+ allFound = false;
+ }
+ } catch (SQLException sqlex) {
+ //
+ // Log the exception and go down the old path
+ //
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logException(this,
+ "exception while retrieving field names", sqlex);
+ }
+ allFound = false;
+ }
+ }
+
+ if (!allFound) {
+
+ // 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 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_);
+ 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 < libList.length && !found; i++) {
+ if (libList[i].length() != 0) {
+ rs.beforeFirst(); // re-position to before the first row
+ while (rs.next() && !found) {
+ if (rs.getString(1).equals(libList[i])) {
+ schema = rs.getString(1);
+ found = true; // we found a procedure that matches our
+ // criteria
+ }
+ }
+ }
+ }
+ rs.close(); // @SS
+ s1.close(); // @SS
+ if (!found) // none of the libraries in our library list contain
+ // a stored procedure that we are looking for
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+ }
+ }
+ }
+
+ rs = s.executeQuery("SELECT SPECIFIC_NAME FROM QSYS2"
+ + catalogSeparator + "SYSPROCS WHERE ROUTINE_SCHEMA = '"
+ + unquote(schema) + // @74C @DELIMc
+ "' AND ROUTINE_NAME = '" + unquote(sqlStatement_.getProcedure()) + // @DELIMc
+ "' AND IN_PARMS + OUT_PARMS + INOUT_PARMS = " + parameterCount_);
+
+ // If there are no rows, throw an internal driver exception
+ if (!rs.next())
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+
+ String specificName = rs.getString(1);
+ rs.close(); // @SS
+
+ rs = s
+ .executeQuery("SELECT PARAMETER_NAME, ORDINAL_POSITION FROM QSYS2"
+ + catalogSeparator
+ + "SYSPARMS WHERE "
+ + // @74A
+ " SPECIFIC_NAME = '"
+ + unquoteNoUppercase(specificName)
+ + "' AND SPECIFIC_SCHEMA = '" + unquote(schema) + "'"); // @DELIMc
+
+ while (rs.next()) {
+ count++;
+
+ String colName = rs.getString(1);
+ int colInd = rs.getInt(2);
+ parameterNames_[colInd - 1] = colName;
+
+ if (caseSensitive && colName.equals(parameterName))
+ returnParm = colInd;
+ else if (!caseSensitive && colName.equalsIgnoreCase(parameterName))
+ returnParm = colInd;
+ }
+ } finally // @scan1
+ {
+ if (rs != null) // @scan1
+ rs.close(); // @SS
+ if (s != null) // @scan1
+ s.close(); // @SS
+ }
+
+ // If the number of parm names didn't equal the number of parameters,
+ // throw
+ // an exception (INTERNAL).
+ if (count != parameterCount_) {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+ }
+ }
+ }
+
+ // Throw an exception if the column name is not found (COLUMN NOT FOUND).
+ if (returnParm == 0)
+ JDError.throwSQLException(this, JDError.EXC_COLUMN_NOT_FOUND);
+
+ // If the statement is using the return value parameter, increment the value to
+ // compensate for the return value parameter. @K2A.
+ if (useReturnValueParameter_) {
+ returnParm++;
+ }
+ return returnParm;
+ }
+
+ // @PDA jdbc40 move from callableStatement
+ private static final String unquote(String name) {
+ return JDUtilities.prepareForSingleQuotes(name, true);
+ }
+
+ // @PDA jdbc40 move from callableStatement
+ private static final String unquoteNoUppercase(String name) {
+ return JDUtilities.prepareForSingleQuotes(name, false);
+ }
+
+ // @PDA jdbc40 helper method
+ private void setInputStream(int parameterIndex, InputStream x)
+ throws SQLException {
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (x != null) {
+ // If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (sqlType == SQLData.CLOB_LOCATOR || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR || // @pdc jdbc40
+ sqlType == SQLData.NCLOB_LOCATOR || // @pda jdbc40
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ sqlData.set(x, null, -2);// new ConvTableReader(x, 819, 0,
+ // LOB_BLOCK_SIZE), null, -2); //@readerlen
+ // -2 flag to read all of reader bytes
+ } else {
+ sqlData.set(x, null, -2);// sqlData.set
+ // (JDUtilities.readerToString(new
+ // ConvTableReader(x, 819, 0,
+ // LOB_BLOCK_SIZE)), null, -1); //@readerlen
+ // -2 flag to read all of reader bytes
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (x == null);
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+ }
+
+ // @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.
+ *
+ * PreparedStatement
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setAsciiStream(int parameterIndex, InputStream x)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setAsciiStream(int, InputStream)");
+ if (x == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+ setInputStream(parameterIndex, 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.
+ *
+ * PreparedStatement
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setBinaryStream(int parameterIndex, InputStream x)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setBinaryStream(int, InputStream)");
+ if (x == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+ setInputStream(parameterIndex, 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 server 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
+ * server as a LONGVARBINARY
or a BLOB
+ *
+ * @param parameterIndex
+ * @param inputStream
+ * An object that contains the data to set the parameter value to.
+ * @throws SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; if a database access error occurs; this method
+ * is called on a closed PreparedStatement
or if
+ * parameterIndex does not correspond to a parameter marker in the
+ * SQL statement,
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ *
+ */
+ public void setBlob(int parameterIndex, InputStream inputStream)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setBlob(int, InputStream)");
+ if (inputStream == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+ setInputStream(parameterIndex, inputStream);
+ }
+
+ // @PDA jdbc40 helper
+ private void setReader(int parameterIndex, Reader reader) throws SQLException {
+ // @J0A added the code from setValue in this method because streams and
+ // readers are handled specially
+ synchronized (internalLock_) {
+ checkOpen();
+
+ // Validate the parameter index.
+ if ((parameterIndex < 1) || (parameterIndex > parameterCount_))
+ JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Check if the parameter index refers to the return value parameter.
+ // This is an OUT parameter, so sets are not allowed. If its not
+ // parameter index 1, then decrement the parameter index, since we
+ // are "faking" the return value parameter.
+ if (useReturnValueParameter_) {
+ if (parameterIndex == 1)
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+ else
+ --parameterIndex;
+ }
+
+ // Check that the parameter is an input parameter.
+ if (!parameterRow_.isInput(parameterIndex))
+ JDError.throwSQLException(this, JDError.EXC_PARAMETER_TYPE_INVALID);
+
+ // Set the parameter data. If there is a type mismatch,
+ // set() with throw an exception.
+ SQLData sqlData = parameterRow_.getSQLType(parameterIndex);
+ if (reader != null) {
+
+ // If the data is a locator, then set its handle.
+ int sqlType = sqlData.getSQLType(); // @xml3
+ if (sqlType == SQLData.CLOB_LOCATOR || sqlType == SQLData.BLOB_LOCATOR
+ || sqlType == SQLData.DBCLOB_LOCATOR || // @pdc jdbc40
+ sqlType == SQLData.NCLOB_LOCATOR || // @pda jdbc40
+ sqlType == SQLData.XML_LOCATOR) // @xml3
+ {
+ SQLLocator sqlDataAsLocator = (SQLLocator) sqlData;
+ sqlDataAsLocator.setHandle(parameterRow_
+ .getFieldLOBLocatorHandle(parameterIndex));
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation(
+ this,
+ "locator handle: "
+ + parameterRow_.getFieldLOBLocatorHandle(parameterIndex));
+ sqlData.set(reader, null, -2); // @readerlen -2 flag to read all of
+ // reader chars
+ } else {
+ sqlData.set(JDUtilities.readerToString(reader), null, -1);
+ }
+
+ testDataTruncation(parameterIndex, sqlData);
+ }
+ // Parameters can be null; you can call one of the set methods to null out
+ // a
+ // field of the database.
+ parameterNulls_[parameterIndex - 1] = (reader == null);
+ parameterSet_[parameterIndex - 1] = true;
+
+ }
+
+ }
+
+ // @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.
+ *
+ * setCharacterStream
+ * which takes a length parameter.
+ *
+ * @param parameterIndex
+ * @param reader
+ * the java.io.Reader
object that contains the Unicode
+ * data
+ * @exception SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; if a database access error occurs or this
+ * method is called on a closed PreparedStatement
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setCharacterStream(int parameterIndex, Reader reader)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setCharacterStream(int, Reader)");
+ if (reader == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+
+ setReader(parameterIndex, 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 server 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 server as a
+ * LONGVARCHAR
or a CLOB
+ *
+ * setClob
which
+ * takes a length parameter.
+ *
+ * @param parameterIndex
+ * @param reader
+ * An object that contains the data to set the parameter value to.
+ * @throws SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; if a database access error occurs; this method
+ * is called on a closed PreparedStatement
or if
+ * parameterIndex does not correspond to a parameter marker in the
+ * SQL statement
+ *
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setClob(int parameterIndex, Reader reader) throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setClob(int, Reader)");
+ if (reader == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+
+ setReader(parameterIndex, 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.
+ *
+ * setNCharacterStream
which takes a length parameter.
+ *
+ * @param parameterIndex
+ * @param value
+ * the parameter value
+ * @throws SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; 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 PreparedStatement
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setNCharacterStream(int parameterIndex, Reader value)
+ throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setNCharacterStream(int, Reader)");
+ if (value == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+
+ setReader(parameterIndex, 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 server 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
+ * server as a LONGNVARCHAR
or a NCLOB
+ * setNClob
which
+ * takes a length parameter.
+ *
+ * @param parameterIndex
+ * @param reader
+ * An object that contains the data to set the parameter value to.
+ * @throws SQLException
+ * if parameterIndex does not correspond to a parameter marker in
+ * the SQL statement; 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 PreparedStatement
+ * @throws SQLFeatureNotSupportedException
+ * if the JDBC driver does not support this method
+ */
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+ if (JDTrace.isTraceOn()) {
+ JDTrace.logInformation(this, "setNClob(int, Reader)");
+ if (reader == null)
+ JDTrace.logInformation(this, "parameter index: " + parameterIndex
+ + " value: NULL");
+ }
+
+ setReader(parameterIndex, reader);
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCResultSet.java b/jdbc40/com/ibm/as400/access/AS400JDBCResultSet.java
new file mode 100644
index 000000000..1133a3a76
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCResultSet.java
@@ -0,0 +1,7508 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCResultSet.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.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DataTruncation;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+/* ifdef JDBC40 */
+import java.sql.Types;
+/* endif */
+import java.util.Calendar;
+import java.util.Map;
+
+
+
+/**
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @exception SQLException If the result set is not open.
+ **/
+ public int getConcurrency ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+
+ //@cur return value from cursor attribues if exists else return value as done in pre 550
+ if ( statement_ != null ) //@cur
+ { //@cur
+ if( statement_.cursor_.getCursorAttributeUpdatable() == 0) //@cur
+ return ResultSet.CONCUR_READ_ONLY; //@cur
+ else if( statement_.cursor_.getCursorAttributeUpdatable() == 1) //@cur
+ return ResultSet.CONCUR_UPDATABLE; //@cur
+ else //@cur
+ return concurrency_; //@cur
+ } //@cur
+ else //@cur
+ return concurrency_;
+ }
+ }
+
+
+
+ // @D3C
+ /**
+ Returns the name of the SQL cursor in use by the result set.
+ In SQL, results are retrieved through a named cursor. The
+ current row of a result can be updated or deleted using a
+ positioned UPDATE or DELETE statement that references a
+ cursor name.
+
+
+
+
+
+
+ @exception SQLException If the result is not open.
+ **/
+ public int getFetchDirection ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return fetchDirection_;
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the fetch size.
+
+ @return The fetch size.
+
+ @exception SQLException If the result is not open.
+ **/
+ public int getFetchSize ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+ return fetchSize_;
+ }
+ }
+
+
+
+ /**
+ Returns the row cache.
+
+ @return The row cache.
+ **/
+ JDRowCache getRowCache ()
+ {
+ return rowCache_;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+ **/
+ // Implementation note:
+ //
+ // * I made a conscious decision not to return the
+ // DatabaseMetaData's statement, if any, since I do
+ // not want users to be able to execute their own
+ // statements using this.
+ //
+ public Statement getStatement ()
+ throws SQLException
+ {
+ if(isMetadataResultSet)//@mdrs
+ return null; //@mdrs
+ else //@mdrs
+ return statement_;
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the result set type. If the statement requested a result set type
+ ResultSet.TYPE_FORWARD_ONLY, then the result set type will be
+ ResultSet.TYPE_FORWARD_ONLY. Otherwise, the result set type may be a type
+ other than the requested type if the SQL statement that generated the
+ result set specified a different cursor type when opening the cursor.
+
+ @return The result set type. Valid values are:
+
+
+
+
+
+ @exception SQLException If the result set is not open.
+ @since Modification 5
+ **/
+ public int getType ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A
+ checkOpen ();
+
+ // Always return FORWARD_ONLY if the application requested forward only
+ // If this logic changes, also change the similar logic in AS400JDBCStatement. @C4A
+ if (type_ == ResultSet.TYPE_FORWARD_ONLY) return ResultSet.TYPE_FORWARD_ONLY;
+
+ //@cur return value from cursor attributes if exists else return value as done in pre 550
+ if( statement_ != null ) //@cur
+ { //@cur
+ if(statement_.cursor_.getCursorAttributeScrollable() == 0) //@cur
+ return ResultSet.TYPE_FORWARD_ONLY; //@cur
+ else if(statement_.cursor_.getCursorAttributeSensitive() == 0) //@cur
+ return ResultSet.TYPE_SCROLL_INSENSITIVE; //@cur
+ else if(statement_.cursor_.getCursorAttributeSensitive() == 1) //@cur
+ return ResultSet.TYPE_SCROLL_SENSITIVE; //@cur
+ else //@cur
+ return type_; //@cur
+ } //@cur
+ else //@cur
+ return type_;
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Returns the value of an SQL DATALINK output parameter as a
+ java.net.URL object.
+
+ @param columnIndex 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.
+ @since Modification 5
+ **/
+ public URL getURL (int columnIndex)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+ try
+ { String string = getString(columnIndex);
+ if(string == null)
+ return null;
+ return new java.net.URL(string);
+ }
+ catch(MalformedURLException e)
+ {
+ // To be consistent with other testcases where the type does not match,
+ // return a data type mismatch.
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH, e);
+ return null;
+ }
+ }
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ 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 URL getURL (String columnName)
+ throws SQLException
+ {
+ return getURL(findColumn(columnName));
+ }
+
+
+
+ /**
+ 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 SQLWarning getWarnings ()
+ throws SQLException
+ {
+ return sqlWarning_;
+ }
+
+
+
+ /**
+ Indicates if the result set is closed.
+
+ @return true if this result set is closed;
+ false otherwise.
+ **/
+ //@PDA jdbc40 make public and allow SQLException
+ public boolean isClosed () throws SQLException
+ {
+ return closed_;
+ }
+
+
+
+ /**
+ Posts a warning for this result set.
+
+ @param sqlWarning The warning.
+ **/
+ void postWarning (SQLWarning sqlWarning)
+ {
+ if(sqlWarning_ == null)
+ sqlWarning_ = sqlWarning;
+ else
+ sqlWarning_.setNextWarning (sqlWarning);
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Sets the direction in which the rows in a result set are
+ processed.
+
+ @param fetchDirection 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.
+ **/
+ //
+ // Implementation note:
+ //
+ // The fetch direction is intended to be a hint for the driver
+ // to do some optimization (like fetch size helps with record
+ // blocking). However, we currently don't do anything with it.
+ // I attempted to document this fact in the javadoc, but could
+ // not come up with a wording that is not confusing. I think it
+ // is okay NOT to document the fact that we ignore this setting,
+ // since it would not affect the behavior of the driver anyway.
+ //
+ public void setFetchDirection (int fetchDirection)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @D1A //@cur
+ if(((fetchDirection != FETCH_FORWARD)
+ && (fetchDirection != FETCH_REVERSE)
+ && (fetchDirection != FETCH_UNKNOWN))
+ || ((getType() == ResultSet.TYPE_FORWARD_ONLY)
+ && (fetchDirection != ResultSet.FETCH_FORWARD)))
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ checkOpen ();
+ fetchDirection_ = fetchDirection;
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Fetch direction", fetchDirection_);
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ 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.
+
+ ResultSet
object
+ * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT
or ResultSet.CLOSE_CURSORS_AT_COMMIT
+ * The holdability is derived in this order of precedence:
+
+
+ Full functionality of #1 and #2 requires OS/400 v5r2
+ or IBM i. If connecting to OS/400 V5R1 or earlier,
+ the value specified on these two methods will be ignored and the default holdability
+ will be the value of #3.
+ * @throws SQLException if a database error occurs
+ */
+ public int getHoldability() throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+
+ //@cur return value from cursor attribues if exists else return value as done in pre 550
+ if( statement_ != null ) //@cur
+ { //@cur
+ int vrm = 0; //@cur3
+ if(connection_ != null) //@cur3
+ vrm = ((AS400JDBCConnection)connection_).getVRM(); //@cur3
+ if(statement_.cursor_.getCursorAttributeHoldable() == 0
+ && (vrm <= JDUtilities.vrm610
+ || (vrm >= JDUtilities.vrm710 && statement_.cursor_.getCursorIsolationLevel() != 0))) //@cur //@cur3 *none is always hold
+ return ResultSet.CLOSE_CURSORS_AT_COMMIT; //@cur
+ else if(statement_.cursor_.getCursorAttributeHoldable() == 1
+ || (vrm >= JDUtilities.vrm710 && statement_.cursor_.getCursorIsolationLevel() == 0)) //@cur //@cur3
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT; //@cur
+ else //@cur
+ { //@cur
+ //not able to get from cursor attrs from hostserver
+ if((statement_.resultSetHoldability_ == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) ||
+ (statement_.resultSetHoldability_ == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT))
+ {
+ return statement_.resultSetHoldability_;
+ }
+ }
+ } //@cur
+
+ //if above cannot determine holdability, then do best guess
+ if(connection_ instanceof AS400JDBCConnection && connection_ != null) //@cur
+ return ((AS400JDBCConnection) connection_).getHoldability(); //@cur CAST needed for JDK 1.3
+ else //@cur
+ return ResultSet.CLOSE_CURSORS_AT_COMMIT; //@cur (if no statment exists for this, then safest is to return close at commit to prevent cursor reuse errors)
+ }
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Retrieves the value of the designated column in the current row
+ * of this cursor hold
+ driver property.ResultSet
object as a
+ * java.io.Reader
object.
+ * It is intended for use when
+ * accessing NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * @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 columnIndex
+ * @exception SQLException if a database access error occurs
+ */
+ public Reader getNCharacterStream(int columnIndex) throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ SQLData data = getValue (columnIndex);
+ Reader value = (data == null) ? null : data.getNCharacterStream ();
+ openReader_ = value;
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Retrieves the value of the designated column in the current row
+ * of this ResultSet
object as a
+ * java.io.Reader
object.
+ * It is intended for use when
+ * accessing NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * @param columnName the name of the column
+ * @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
+ * @exception SQLException if a database access error occurs
+ */
+ public Reader getNCharacterStream(String columnName) throws SQLException
+ {
+ return getNCharacterStream (findColumn (columnName));
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex
+ * @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 NClob getNClob(int columnIndex) throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ SQLData data = getValue (columnIndex);
+ NClob value = (data == null) ? null : data.getNClob ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 the name of the column from which to retrieve the value
+ * @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 occurs
+ */
+/* ifdef JDBC40 */
+ public NClob getNClob(String columnName) throws SQLException
+ {
+ return getNClob (findColumn (columnName));
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex
+ * @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 columnIndex) throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ SQLData data = getValue (columnIndex);
+ String value = (data == null) ? null : data.getNString ();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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 the SQL name of the 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(String columnName) throws SQLException
+ {
+ return getNString (findColumn (columnName));
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex 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 RowId getRowId(int columnIndex) throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ SQLData data = getValue (columnIndex);
+ RowId value = (data == null) ? null : data.getRowId();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+/* endif */
+
+
+
+ //@pda jdbc40
+ /**
+ * 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 name of the column
+ * @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 RowId getRowId(String columnName) throws SQLException
+ {
+ return getRowId(findColumn (columnName));
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex
+ * @return a SQLXML
object that maps an SQL XML
value
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML(int columnIndex) throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ SQLData data = getValue (columnIndex);
+ SQLXML value = (data == null) ? null : data.getSQLXML();
+ testDataTruncation (columnIndex, data, false); //@trunc //@trunc2
+ return value;
+ }
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * 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 the name of the column from which to retrieve the value
+ * @return a SQLXML
object that maps an SQL XML
value
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML(String columnName) throws SQLException
+ {
+ return getSQLXML(findColumn (columnName));
+ }
+/* endif */
+
+
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a java.sql.NClob
value.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @param nClob 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
+ */
+/* ifdef JDBC40 */
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException
+ {
+ updateValue (columnIndex, nClob, null, -1);
+ }
+/* endif */
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a java.sql.NClob
value.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnName name of the column
+ * @param nClob 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
+ */
+/* ifdef JDBC40 */
+ public void updateNClob(String columnName, NClob nClob) throws SQLException
+ {
+ updateNClob (findColumn (columnName), nClob);
+
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a String
value.
+ * It is intended for use when updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @param nString 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 columnIndex, String nString) throws SQLException
+ {
+ updateValue (columnIndex, nString, null, -1);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a String
value.
+ * It is intended for use when updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnName name of the Column
+ * @param nString 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 nString) throws SQLException
+ {
+ updateNString (findColumn (columnName), nString);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a RowId
value. The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ *
+ * @param columnIndex
+ * @param x the column value
+ * @throws SQLException if a database access occurs
+ */
+/* ifdef JDBC40 */
+ public void updateRowId(int columnIndex, RowId x) throws SQLException
+ {
+ updateValue (columnIndex, x, null, -1);
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a RowId
value. The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ *
+ * @param columnName the name of the column
+ * @param x the column value
+ * @throws SQLException if a database access occurs
+ */
+/* ifdef JDBC40 */
+ public void updateRowId(String columnName, RowId x) throws SQLException
+ {
+ updateRowId (findColumn (columnName), x);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.SQLXML
value.
+ * The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ * @param columnIndex
+ * @param xmlObject the value for the column to be updated
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException
+ {
+ //@xmlspec special handling of blob/clob column types
+ if(xmlObject == null) //@xmlspec3
+ { //@xmlspec3
+ updateValue (columnIndex, xmlObject, null, -1); //@xmlspec3
+ return; //@xmlspec3
+ } //@xmlspec3
+
+ int sqlDataType;
+ if(updateRow_ != null) //@nulltype
+ sqlDataType = updateRow_.getSQLData (columnIndex).getType(); //@xmlspec //@nulltype
+ else
+ sqlDataType = Types.SQLXML; //@nulltype dummy type so processing continues
+
+
+ switch(sqlDataType) { //@xmlspec
+ case Types.CLOB: //@xmlspec
+ updateCharacterStream(columnIndex, xmlObject.getCharacterStream());//@xmlspec
+ break; //@xmlspec
+ case Types.BLOB: //@xmlspec
+ updateBinaryStream(columnIndex, xmlObject.getBinaryStream()); //@xmlspec
+ break; //@xmlspec
+ default: //@xmlspec
+ updateValue (columnIndex, xmlObject, null, -1);
+ }
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.SQLXML
value.
+ * The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ *
+ * @param columnName the name of the column
+ * @param xmlObject the column value
+ * @throws SQLException if a database access occurs
+ */
+/* ifdef JDBC40 */
+ public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException
+ {
+ updateSQLXML(findColumn(columnName), xmlObject);
+ }
+/* endif */
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCResultSet", "java.sql.ResultSet" };
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with an ascii stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.streamToString (x, (int)length, "ISO8859_1"), null, -1);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with an ascii stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the column name
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ updateAsciiStream (findColumn (columnLabel), x, length);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a binary stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.streamToBytes (x, (int)length), null, -1);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a binary stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ updateBinaryStream (findColumn (columnLabel), x, length);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @param length the number of bytes in the parameter data.
+ * @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 updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (inputStream == null) ? null : JDUtilities.streamToBytes (inputStream, (int)length), null, -1);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @param length the number of bytes in the parameter data.
+ * @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 updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException
+ {
+ updateBlob (findColumn (columnLabel), inputStream, length);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.readerToString (x, (int)length), null, -1);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateCharacterStream (findColumn (columnLabel), reader, length);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @param reader An object that contains the data to set the parameter value to.
+ * @param length the number of characters in the parameter data.
+ * @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 updateClob(int columnIndex, Reader reader, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (reader == null) ? null : JDUtilities.readerToString (reader, (int)length), null, -1);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @param length the number of characters in the parameter data.
+ * @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 updateClob(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateClob (findColumn (columnLabel), reader, length);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.readerToString (x, (int)length), null, -1);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateNCharacterStream (findColumn (columnLabel), reader, length);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex
+ * @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 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 columnIndex, Reader reader, long length) throws SQLException
+ {
+ if(length < 0)
+ JDError.throwSQLException (JDError.EXC_BUFFER_LENGTH_INVALID);
+
+ updateValue (columnIndex,
+ (reader == null) ? null : JDUtilities.readerToString (reader, (int)length), null, -1);
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @param length the number of characters in the parameter data.
+ * @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 updateNClob(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateNClob (findColumn (columnLabel), reader, length);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with an ascii stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateAsciiStream
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @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 updateAsciiStream(int columnIndex, InputStream x) throws SQLException
+ {
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.streamToBytes (x), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with an ascii stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateAsciiStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param x the new column value
+ * @exception SQLException if the columnLabel 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 updateAsciiStream(String columnLabel, InputStream x) throws SQLException
+ {
+ updateAsciiStream (findColumn (columnLabel), x);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a binary stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBinaryStream
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @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 updateBinaryStream(int columnIndex, InputStream x) throws SQLException
+ {
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.streamToBytes (x), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a binary stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBinaryStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param x the new column value
+ * @exception SQLException if the columnLabel 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 updateBinaryStream(String columnLabel, InputStream x) throws SQLException
+ {
+ updateBinaryStream (findColumn (columnLabel), x);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBlob
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @param inputStream 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 columnIndex, InputStream inputStream) throws SQLException
+ {
+ updateValue (columnIndex,
+ (inputStream == null) ? null : JDUtilities.streamToBytes (inputStream), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBlob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @exception SQLException if the columnLabel 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 columnLabel, InputStream inputStream) throws SQLException
+ {
+ updateBlob (findColumn (columnLabel), inputStream);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateCharacterStream
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @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 updateCharacterStream(int columnIndex, Reader x) throws SQLException
+ {
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.readerToString(x), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateCharacterStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * the new column value
+ * @exception SQLException if the columnLabel 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 updateCharacterStream(String columnLabel, Reader reader) throws SQLException
+ {
+ updateCharacterStream (findColumn (columnLabel), reader);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateClob
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @param reader 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 updateClob(int columnIndex, Reader reader) throws SQLException
+ {
+ updateValue (columnIndex,
+ (reader == null) ? null : JDUtilities.readerToString(reader), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateClob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @exception SQLException if the columnLabel 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 updateClob(String columnLabel, Reader reader) throws SQLException
+ {
+ updateClob (findColumn (columnLabel), reader);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNCharacterStream
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @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 columnIndex, Reader x) throws SQLException
+ {
+ updateValue (columnIndex,
+ (x == null) ? null : JDUtilities.readerToString(x), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNCharacterStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * the new column value
+ * @exception SQLException if the columnLabel 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 columnLabel, Reader reader) throws SQLException
+ {
+ updateNCharacterStream(findColumn (columnLabel), reader);
+ }
+
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNClob
which takes a length parameter.
+ *
+ * @param columnIndex
+ * @param reader 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 columnIndex, Reader reader) throws SQLException
+ {
+ updateValue (columnIndex,
+ (reader == null) ? null : JDUtilities.readerToString(reader), null, -1);
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNClob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @throws SQLException if the columnLabel 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 columnLabel, Reader reader) throws SQLException
+ {
+ updateNClob (findColumn (columnLabel), reader);
+ }
+
+
+
+
+ //@EIA new method
+ /**
+ Updates a column for the specified index, and performs all
+ appropriate validation.
+
+ Note: this is the same type of method as updateValue() above, but we
+ have no way to pass in the special values without hacking some sort
+ of flag string for the value, and that seemed to be a messy and slow
+ way to do this.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The parameter 1="default" or 2="unassigned".
+
+
+ @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.
+ **/
+ private void updateValueExtendedIndicator (int columnIndex, int columnValue)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ beforeUpdate ();
+
+ // Check that there is a current row.
+ if((positionValid_ == false) && (positionInsert_ == false))
+ JDError.throwSQLException (JDError.EXC_CURSOR_POSITION_INVALID);
+
+ // Validate The column index.
+ if((columnIndex < 1) || (columnIndex > columnCount_))
+ JDError.throwSQLException (JDError.EXC_DESCRIPTOR_INDEX_INVALID);
+
+ // Set the update value. If there is a type mismatch,
+ // set() with throw an exception.
+
+ int columnIndex0 = columnIndex - 1;
+
+ updateNulls_[columnIndex0] = false;
+ updateDefaults_[columnIndex0] = columnValue == 1 ? true: false;
+ updateUnassigned_[columnIndex0] = columnValue == 2 ? true: false;
+ updateSet_[columnIndex0] = true;
+
+ }
+ }
+
+
+ /**
+ * Retrieves the value of the designated column in the current row of this ResultSet object and will convert
+ * from the SQL type of the column to the requested Java data type, if the conversion is supported.
+ * If the conversion is not supported or null is specified for the type, a SQLException is thrown.
+ *
+ * RowId
to the specified object. The result is
+ * true
if and only if the argument is not null and is a RowId
+ * object that represents the same ROWID as this object.
+ * RowId
+ * when comparing it to another RowId
. If both are valid, and
+ * both are from the same table on the same data source, then if they are equal
+ * they identify
+ * the same row; if one or more is no longer guaranteed to be valid, or if
+ * they originate from different data sources, or different tables on the
+ * same data source, they may be equal but still
+ * not identify the same row.
+ *
+ * @param obj the Object
to compare this RowId
object
+ * against.
+ * @return true if the RowId
s are equal; false otherwise
+ */
+/* ifdef JDBC40 */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof RowId))
+ {
+ return false;
+ }
+
+ byte[] otherBytes = ((RowId) obj).getBytes();
+ if (data_.length != otherBytes.length)
+ return false;
+
+ for (int i = 0; i < data_.length; i++)
+ {
+ if (data_[i] != otherBytes[i])
+ return false;
+ }
+ return true;
+ }
+/* endif */
+
+ /**
+ * Returns an array of bytes representing the value of the SQL ROWID
+ * designated by this java.sql.RowId
object.
+ *
+ * @return an array of bytes, whose length is determined by the driver supplying
+ * the connection, representing the value of the ROWID designated by this
+ * java.sql.RowId object.
+ */
+ public byte[] getBytes()
+ {
+ return data_;
+ }
+
+ /**
+ * Returns a String representing the value of the SQL ROWID designated by this
+ * java.sql.RowId
object.
+ * java.sql.Date.toString()
+ * returns the contents of its DATE as the String
"2004-03-17"
+ * rather than as DATE literal in SQL (which would have been the String
+ * DATE "2004-03-17"), toString()
+ * returns the contents of its ROWID in a form specific to the driver supplying
+ * the connection, and possibly not as a ROWID
literal.
+ * Toolbox converts RowId bytes to HEX string format.
+ *
+ * @return a String whose format is determined by the driver supplying the
+ * connection, representing the value of the ROWID
designated
+ * by this java.sql.RowId
object.
+ */
+ public String toString()
+ {
+ return bytesToString(data_);
+ }
+
+
+ static final String bytesToString(final byte[] b)
+ {
+ return bytesToString(b, 0, b.length);
+ }
+
+ static final String bytesToString(final byte[] b, int offset, int length)
+ {
+ char[] c = new char[length*2];
+ int num = bytesToString(b, offset, length, c, 0);
+ return new String(c, 0, num);
+ }
+
+
+ static final int bytesToString(final byte[] b, int offset, int length, final char[] c, int coffset)
+ {
+ for(int i=0; iRowId
object.
+ *
+ * @return a hash code for the RowId
+ */
+ public int hashCode()
+ {
+ //for now, use String's implementation. seems good enough.
+ return this.toString().hashCode();
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCRowSet.java b/jdbc40/com/ibm/as400/access/AS400JDBCRowSet.java
new file mode 100644
index 000000000..17e39ddb0
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCRowSet.java
@@ -0,0 +1,7394 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCRowSet.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 javax.sql.DataSource;
+import javax.sql.RowSet;
+import javax.sql.RowSetEvent;
+import javax.sql.RowSetListener;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.net.URL; //@G4A JDBC 3.0
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+/* endif */
+
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.Hashtable; //@A2A
+import java.util.Map;
+
+/**
+* The AS400JDBCRowSet class represents a connected rowset that encapsulates an JDBC result set.
+* The database connection is maintained while in use.
+*
+*
+*
+* DriverManager.registerDriver(new AS400JDBCDriver());
+* AS400JDBCRowSet rowset = new AS400JDBCRowSet("jdbc:as400://mySystem","myUser", "myPassword");
+*
+* // Set the command used to populate the list.
+* rowset.setCommand("SELECT * FROM MYLIB.DATABASE");
+*
+* // Populate the rowset.
+* rowset.execute();
+*
+* // Update the customer balances.
+* while (rowset.next())
+* {
+* double newBalance = rowset.getDouble("BALANCE") + july_statements.getPurchases(rowset.getString("CUSTNUM"));
+* rowset.updateDouble("BALANCE", newBalance);
+* rowset.updateRow();
+* }
+*
+*
+*
+* // Get the data source that is registered in JNDI (assumes JNDI environment is set).
+* Context context = new InitialContext();
+* AS400JDBCDataSource dataSource = (AS400JDBCDataSource) context.lookup("jdbc/customer");
+*
+* AS400JDBCRowSet rowset = new AS400JDBCRowSet();
+* rowset.setDataSourceName("jdbc/customer");
+* rowset.setUsername("myuser");
+* rowset.setPassword("myPasswd");
+*
+* // Set the prepared statement and initialize the parameters.
+* rowset.setCommand("SELECT * FROM MYLIBRARY.MYTABLE WHERE STATE = ? AND BALANCE > ?");
+* rowset.setString(1, "MINNESOTA");
+* rowset.setDouble(2, MAXIMUM_LIMIT);
+*
+* // Populate the rowset.
+* rowset.execute();
+*
+*
+**/
+public class AS400JDBCRowSet
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+implements RowSet, Serializable // @A3C
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+
+
+ static final long serialVersionUID = 4L;
+
+
+
+ static final String className_ = "AS400JDBCRowSet";
+ private String command_; // The command used to create the result set.
+ private String dataSourceName_; // The name of the data source.
+ private boolean useDataSource_ = true; // Whether the dataSource specified is used.
+ private String url_; // The user defined URL used to make the connection.
+ private String username_; // The user name used to make the connection.
+ private String password_; // The password used to make the connection.
+
+ // Toolbox classes.
+ private Connection connection_; // The JDBC connection.
+ private DataSource dataSource_; // The dataSource used to make the connection.
+ private AS400JDBCPreparedStatement statement_; // The prepared statement. //@pdc jdbc40
+ private transient AS400JDBCResultSet resultSet_; // The result set. @G4C //@scan1
+ private transient AS400JDBCRowSetEventSupport eventSupport_; // RowSetListener support. @A3C
+ private Context context_ = null; //@A1A // The JNDI naming context which specifies how naming
+ // and directory services are accessed.
+ private Hashtable environment_ = null; //@A2A // The jndi environment properties.
+
+ // Connection properties.
+ private boolean isReadOnly_ = false;
+ private int transactionIsolation_ = Connection.TRANSACTION_READ_UNCOMMITTED;
+ private Map typeMap_;
+
+ // Statement properties.
+ private boolean createNewStatement_ = true;
+ private int concurrency_ = ResultSet.CONCUR_READ_ONLY;
+ private boolean escapeProcessing_ = true;
+ private int type_ = ResultSet.TYPE_FORWARD_ONLY;
+
+ private transient PropertyChangeSupport changes_; // @A3C
+
+ /**
+ * Constructs a default AS400JDBCRowSet object.
+ **/
+ public AS400JDBCRowSet()
+ {
+ // @A3D eventSupport_ = new AS400JDBCRowSetEventSupport();
+ initializeTransient(); // @A3A
+ }
+
+ /**
+ * Constructs an AS400JDBCRowset with the specified dataSourceName.
+ * @param dataSourceName The name of the data source used to make the connection.
+ **/
+ public AS400JDBCRowSet(String dataSourceName)
+ {
+ this();
+ setDataSourceName(dataSourceName);
+ }
+
+ /**
+ * Constructs an AS400JDBCRowSet with the specified parameters.
+ * @param url The url used to make the connection.
+ * @param username The user name.
+ * @param password The password.
+ **/
+ public AS400JDBCRowSet(String url, String username, String password)
+ {
+ this();
+ setUrl(url);
+ setUsername(username);
+ setPassword(password);
+ }
+
+ /**
+ * Positions the cursor to an absolute row number.
+ *
+ *
+*
+*
+ *
+ * The following properties may be used to create a statement to execute a command:
+ *
+ *
+ *
+ * @exception SQLException If a database error occurs.
+ **/
+ public void execute() throws SQLException
+ {
+ if (JDTrace.isTraceOn ())
+ JDTrace.logInformation (this, "execute()");
+
+ if (createNewStatement_)
+ createStatement();
+
+ if (command_.toUpperCase().indexOf("SELECT") != -1) // Fix for JTOpen Bug 4121
+ {
+ resultSet_ = (AS400JDBCResultSet)statement_.executeQuery(); //@G4C
+
+ // Notify the listeners.
+ eventSupport_.fireRowSetChanged(new RowSetEvent(this));
+ }
+ else
+ {
+ statement_.executeUpdate();
+ }
+
+ }
+
+ /**
+ * Closes the Statement and Connection.
+ * @exception SQLException If a database error occurs.
+ **/
+ protected void finalize() throws SQLException
+ {
+ try
+ {
+ close();
+ }
+ catch (SQLException e)
+ {
+ JDError.throwSQLException (JDError.EXC_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.findColumn(columnName);
+ }
+
+ /**
+ * Positions the cursor to the first row.
+ * If an InputStream from the current row is open, it is implicitly closed.
+ * In addition, all warnings and pending updates are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.first();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+
+ /**
+ * Returns the value of a column as an Array object.
+ * DB2 for IBM i does not support arrays.
+ *
+ * @param columnIndex 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 arrays.
+ **/
+ public Array getArray (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getArray(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as an Array object.
+ * DB2 for IBM i does not support arrays.
+ *
+ * @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 arrays.
+ **/
+ public Array getArray (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getArray(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a stream of ASCII
+ * characters. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ * BLOB. All of the data in the returned stream must be read
+ * prior to getting the value of any other column. The next
+ * call to a get method implicitly closes the stream.
+ *
+ * @param columnIndex 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 InputStream getAsciiStream (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getAsciiStream(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a stream of ASCII
+ * characters. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ * BLOB. All of the data in the returned stream must be read
+ * prior to getting the value of any other column. The next
+ * call to a get method implicitly closes the 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public InputStream getAsciiStream (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getAsciiStream(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a BigDecimal object. This
+ * can be used to get values from columns with SQL types
+ * SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 BigDecimal getBigDecimal (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBigDecimal(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a BigDecimal object. This
+ * can be used to get values from columns with SQL types
+ * SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 name is not found,
+ * or the requested conversion is not valid.
+ **/
+ public BigDecimal getBigDecimal (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBigDecimal(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a BigDecimal object. This
+ * can be used to get values from columns with SQL types
+ * SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 BigDecimal getBigDecimal (int columnIndex, int scale) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBigDecimal(columnIndex, scale);
+ }
+
+ /**
+ * Returns the value of a column as a BigDecimal object. This
+ * can be used to get values from columns with SQL types
+ * SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 name is not found,
+ * the scale is not valid, or the
+ * requested conversion is not valid.
+ *
+ * @deprecated Use getBigDecimal(String) instead.
+ * @see #getBigDecimal(String)
+ **/
+ public BigDecimal getBigDecimal (String columnName, int scale) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBigDecimal(columnName, scale);
+ }
+
+ /**
+ * Returns the value of a column as a stream of uninterpreted
+ * bytes. This can be used to get values from columns
+ * with SQL types BINARY, VARBINARY, and BLOB. All of the data in
+ * the returned stream must be read prior to getting the
+ * value of any other column. The next call to a get method
+ * implicitly closes the stream.
+ *
+ * @param columnIndex 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 InputStream getBinaryStream (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBinaryStream(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a stream of uninterpreted
+ * bytes. This can be used to get values from columns
+ * with SQL types BINARY, VARBINARY, and BLOB. All of the data in
+ * the returned stream must be read prior to getting the
+ * value of any other column. The next call to a get method
+ * implicitly closes the 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public InputStream getBinaryStream (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBinaryStream(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a Blob object.
+ * This can be used to get values from columns with SQL
+ * types BINARY, VARBINARY, and BLOB.
+ *
+ * @param columnIndex 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 Blob getBlob (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBlob(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a Blob object.
+ * This can be used to get values from columns with SQL
+ * types BINARY, VARBINARY, and BLOB.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Blob getBlob (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBlob(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java boolean value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex The column index (1-based).
+ * @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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBoolean(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a Java boolean value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public boolean getBoolean (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getBoolean(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a Java byte value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 byte getByte (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getByte(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java byte value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 byte getByte (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getByte(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a Java byte array.
+ * This can be used to get values from columns with SQL
+ * types BINARY and VARBINARY.
+ *
+ *
+ *
+ * @exception SQLException If the result set is not open.
+ **/
+ public int getConcurrency () throws SQLException
+ {
+ if (resultSet_ != null)
+ concurrency_ = resultSet_.getConcurrency();
+ return concurrency_;
+ }
+
+ //@A1A
+ /**
+ * Returns the JNDI naming context which provides name-to-object bindings
+ * and methods for retrieving and updating naming and directory services.
+ *
+ * @return The context or null if the value has not been set.
+ *
+ **/
+ public Context getContext ()
+ {
+ return context_;
+ }
+
+ /**
+ * Returns the name of the SQL cursor in use by the result set.
+ * In SQL, results are retrieved through a named cursor. The
+ * current row of a result can be updated or deleted using a
+ * positioned UPDATE or DELETE statement that references a cursor name.
+ *
+ * @return The cursor name.
+ * @exception SQLException If the result is not open.
+ **/
+ public String getCursorName() throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getCursorName();
+ }
+
+ /**
+ * Returns the name of the data source as identified in JNDI.
+ * @return The data source name. The default value is null.
+ **/
+ public String getDataSourceName()
+ {
+ return dataSourceName_;
+ }
+
+ /**
+ * Returns the value of a column as a java.sql.Date object using
+ * the default calendar. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @param columnIndex 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 Date getDate (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDate(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a java.sql.Date object using
+ * the default calendar. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Date getDate (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDate(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Date object using
+ * a calendar other than the default. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @param columnIndex 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.
+ **/
+ public Date getDate (int columnIndex, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDate(columnIndex, calendar);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Date object using
+ * a calendar other than the default. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @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 name is not found,
+ * the calendar is null, or the
+ * requested conversion is not valid.
+ **/
+ public Date getDate (String columnName, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDate(columnName, calendar);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java double value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 double getDouble (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDouble(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java double value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.getDouble(columnName);
+ }
+
+
+ //@A2A
+ /**
+ * Returns a hashtable of standard JNDI environment properties.
+ *
+ * @return The environment properties or null if the value has not been set.
+ *
+ **/
+ public Hashtable getEnvironment ()
+ {
+ return environment_;
+ }
+
+ /**
+ * Indicates if escape processing is enabled (default).
+ * If enabled, escape substitution is done before committing the data.
+ * @return true if enabled; false otherwise.
+ **/
+ public boolean getEscapeProcessing()
+ {
+ return escapeProcessing_ ;
+ }
+
+ /**
+ * Returns the fetch direction.
+ *
+ * @return The fetch direction.
+ * Valid values are:
+ *
+ *
+ *
+ * @exception SQLException If the result is not open.
+ **/
+ public int getFetchDirection() throws SQLException
+ {
+ if (resultSet_ != null)
+ return resultSet_.getFetchDirection();
+
+ if (statement_ == null)
+ return ResultSet.FETCH_FORWARD;
+
+ return statement_.getFetchDirection();
+
+ }
+
+ /**
+ * Returns the number of rows to be fetched from the database when more rows are needed.
+ * The number of rows specified only affects result sets created using this statement.
+ * If the value specified is zero, then the driver will choose an appropriate fetch size.
+ *
+ * This setting only affects statements that meet the criteria specified in the "block criteria" property.
+ * The fetch size is only used if the "block size" property is set to "0".
+ *
+ * @return The fetch size.
+ * @exception SQLException If the result is not open.
+ **/
+ public int getFetchSize() throws SQLException
+ {
+ if (resultSet_ != null)
+ return resultSet_.getFetchSize();
+
+ if (statement_ == null)
+ return 0;
+
+ return statement_.getFetchSize();
+ }
+
+ /**
+ * Returns the value of a column as a Java float value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getFloat(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java float value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 float getFloat (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getFloat(columnName);
+ }
+
+ /**
+ * Returns the value of a column as a Java int value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 int getInt (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getInt(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java int value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.getInt(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java long value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getLong(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java long value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 long getLong (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getLong(columnName);
+ }
+
+ /**
+ * Returns the maximum column size.
+ * This property is only used with column types:
+ *
+ *
+ * @return The maximum size. The default zero of zero indicates no maximum.
+ * @exception SQLException If a database error occurs.
+ **/
+ public int getMaxFieldSize() throws SQLException
+ {
+ if (statement_ == null)
+ return 0;
+ return statement_.getMaxFieldSize();
+ }
+
+ /**
+ * Returns the maximum number of rows for the rowset.
+ * @return The maximum. The default value of zero indicates no maximum.
+ * @exception SQLException If a database error occurs.
+ **/
+ public int getMaxRows() throws SQLException
+ {
+ if (statement_ == null)
+ return 0;
+ return statement_.getMaxRows();
+ }
+
+ /**
+ * Returns the ResultSetMetaData object that describes the
+ * result set's columns.
+ *
+ * @return The metadata object.
+ * @exception SQLException If an error occurs.
+ **/
+ public ResultSetMetaData getMetaData () throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getMetaData();
+ }
+
+
+
+ /**
+ * Returns the value of a column as a Java Object.
+ * This can be used to get values from columns with all
+ * SQL types. If the column is a user-defined type, then the
+ * connection's type map is used to created the object.
+ *
+ * @param columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getObject(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a Java Object.
+ * This can be used to get values from columns with all
+ * SQL types. If the column is a user-defined type, then the
+ * connection's type map is used to created the 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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Object getObject (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getObject(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java Object.
+ *
+ * @param columnIndex The column index (1-based).
+ * @param typeMap 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 columnIndex, Map typeMap) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getObject(columnIndex, typeMap);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java Object.
+ *
+ * @param columnName The column name.
+ * @param typeMap 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 name is not found,
+ * the type map is null, or the
+ * requested conversion is not valid.
+ **/
+ public Object getObject (String columnName, Map typeMap) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getObject(columnName, typeMap);
+ }
+
+ /**
+ * Returns the password used to create the connection.
+ * @return An empty String. For security the password information cannot be accessed.
+ **/
+ public String getPassword()
+ {
+ return "";
+ }
+
+ /**
+ * Returns the maximum wait time in seconds for a statement to execute.
+ * @return The timeout value in seconds. The default value of zero indicates no maximum.
+ * @exception SQLException If a database error occurs.
+ **/
+ public int getQueryTimeout() throws SQLException
+ {
+ validateStatement();
+ return statement_.getQueryTimeout();
+ }
+
+ /**
+ * Returns the value of a column as a Ref object.
+ * DB2 for IBM i does not support structured types.
+ *
+ * @param columnIndex 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 Ref getRef (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getRef(columnIndex);
+ }
+
+
+ /**
+ * 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 Ref getRef (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getRef(columnName);
+ }
+
+ /**
+ * Returns the current row number.
+ *
+ * @return The current row number (1-based). If there is no current
+ * row or if the cursor is positioned on the insert row,
+ * 0 is returned.
+ *
+ * @exception SQLException If the result set is not open.
+ **/
+ public int getRow () throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getRow();
+ }
+
+ /**
+ * Returns the value of a column as a Java short value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @param columnIndex 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 columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getShort(columnIndex);
+ }
+
+
+ /**
+ * Returns the value of a column as a Java short value.
+ * This can be used to get values from columns with SQL
+ * types SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL,
+ * NUMERIC, CHAR, and VARCHAR.
+ *
+ * @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 short getShort (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getShort(columnName);
+ }
+
+
+ /**
+ * 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 Statement getStatement() throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getStatement();
+ }
+
+ /**
+ * Returns the value of a column as a String object.
+ * This can be used to get values from columns with any SQL
+ * type.
+ *
+ * @param columnIndex 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 String getString (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getString(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a String object.
+ * This can be used to get values from columns with any SQL
+ * type.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public String getString (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getString(columnName);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a java.sql.Time object using the
+ * default calendar. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ *
+ * @param columnIndex 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 Time getTime (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTime(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a java.sql.Time object using the
+ * default calendar. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Time getTime (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTime(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Time object using a
+ * calendar other than the default. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ *
+ * @param columnIndex 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.
+ **/
+ public Time getTime (int columnIndex, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTime(columnIndex, calendar);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Time object using a
+ * calendar other than the default. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, TIME, and TIMESTAMP.
+ *
+ * @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 name is not found,
+ * the calendar is null, or the
+ * requested conversion is not valid.
+ **/
+ public Time getTime (String columnName, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTime(columnName, calendar);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a java.sql.Timestamp object
+ * using the default calendar. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @param columnIndex 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 Timestamp getTimestamp (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTimestamp(columnIndex);
+ }
+
+
+
+ /**
+ * Returns the value of a column as a java.sql.Timestamp object
+ * using the default calendar. This can be used to get values
+ * from columns with SQL types CHAR, VARCHAR, DATE, and TIMESTAMP.
+ *
+ * @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 name is not found, or the
+ * requested conversion is not valid.
+ **/
+ public Timestamp getTimestamp (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTimestamp(columnName);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Timestamp object
+ * using a calendar other than the default. This can be used to
+ * get values from columns with SQL types CHAR, VARCHAR, DATE,
+ * and TIMESTAMP.
+ *
+ * @param columnIndex 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.
+ **/
+ public Timestamp getTimestamp (int columnIndex, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTimestamp(columnIndex, calendar);
+ }
+
+
+ /**
+ * Returns the value of a column as a java.sql.Timestamp object
+ * using a calendar other than the default. This can be used to
+ * get values from columns with SQL types CHAR, VARCHAR, DATE,
+ * and TIMESTAMP.
+ *
+ * @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 name is not found,
+ * the calendar is null, or the
+ * requested conversion is not valid.
+ **/
+ public Timestamp getTimestamp (String columnName, Calendar calendar) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getTimestamp(columnName, calendar);
+ }
+
+ /**
+ * Returns the transaction isolation level.
+ * Possible values are:
+ *
+ *
+ * @return The transaction isolation level.
+ **/
+ public int getTransactionIsolation()
+ {
+ try
+ {
+ if (connection_ != null)
+ return connection_.getTransactionIsolation();
+ else
+ return transactionIsolation_;
+ }
+ catch (SQLException e)
+ {
+ JDTrace.logInformation (this, "getTransactionIsolation() database error"); // @G5C
+ return transactionIsolation_;
+ }
+ }
+
+ /**
+ * 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 SQLException
+ {
+ if (resultSet_ != null)
+ return resultSet_.getType();
+ return type_;
+ }
+
+ /**
+ * Returns the type map.
+ * @return The type map. The default value is null.
+ * @exception SQLException If a database error occurs.
+ **/
+ public Map getTypeMap() throws SQLException
+ {
+ if (connection_ != null)
+ return connection_.getTypeMap();
+ return typeMap_;
+ }
+
+ /**
+ * Returns the value of a column as a stream of Unicode
+ * characters. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB, and
+ * BLOB. All of the data in the returned stream must be read
+ * prior to getting the value of any other column. The next
+ * call to a get method implicitly closes the stream.
+ *
+ * @param columnIndex 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 InputStream getUnicodeStream (int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getUnicodeStream(columnIndex);
+ }
+
+ /**
+ * Returns the value of a column as a stream of Unicode
+ * characters. This can be used to get values from columns
+ * with SQL types CHAR, VARCHAR, BINARY, VARBINARY, CLOB,
+ * and BLOB. All of the data in the returned stream must be
+ * read prior to getting the value of any other column. The
+ * next call to a get method implicitly closes the 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 name is not found, or the
+ * requested conversion is not valid.
+ *
+ * @deprecated Use getCharacterStream(String) instead.
+ * @see #getCharacterStream(String)
+ **/
+ public InputStream getUnicodeStream (String columnName) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getUnicodeStream(columnName);
+ }
+
+ /**
+ * Returns the url used in getting a connection.
+ * Either this property or the dataSource property must be set before calling the execute command.
+ * @return The url. The default value is null.
+ **/
+ public String getUrl()
+ {
+ return url_;
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ Returns the value of an SQL DATALINK output parameter as a
+ java.net.URL object.
+
+ @param columnIndex 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.
+ @since Modification 5
+ **/
+ public URL getURL (int columnIndex)
+ throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getURL(columnIndex);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ 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 URL getURL (String columnName)
+ throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getURL(columnName);
+ }
+
+
+ /**
+ * Returns the user used to create the connection.
+ * @return The user. The default is null.
+ **/
+ public String getUsername()
+ {
+ return username_;
+ }
+
+ /**
+ * 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 SQLWarning getWarnings() throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getWarnings();
+ }
+
+ // @A3A
+ /**
+ Initializes all transient data.
+ **/
+ private void initializeTransient ()
+ {
+ eventSupport_ = new AS400JDBCRowSetEventSupport();
+ changes_ = new PropertyChangeSupport(this);
+ resultSet_ = null; //@scan1
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ resultSet_.insertRow();
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.isAfterLast();
+ }
+
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.isBeforeFirst();
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.isFirst();
+ }
+
+ /**
+ * 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 SQLException
+ {
+ validateResultSet();
+ return resultSet_.isLast();
+ }
+
+ /**
+ * Indicates if the rowset is read-only.
+ * @return true if read-only; false otherwise. The default value is false, allowing updates.
+ **/
+ public boolean isReadOnly()
+ {
+ if (connection_ != null)
+ {
+ try
+ {
+ return connection_.isReadOnly();
+ }
+ catch (SQLException e) { /* return local value */
+ }
+ }
+ return isReadOnly_;
+ }
+
+ /**
+ * Indicates if the data source is used to make a connection to the database.
+ * @return true if the data source is used; false if the url is used. The default value is true.
+ **/
+ public boolean isUseDataSource()
+ {
+ return useDataSource_;
+ }
+
+ /**
+ * Positions the cursor to the last row.
+ * If an InputStream from the current row is open, it is
+ * implicitly closed. In addition, all warnings and pending updates
+ * are cleared.
+ *
+ * @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 SQLException
+ {
+ validateResultSet();
+ boolean status = resultSet_.last();
+
+ eventSupport_.fireCursorMoved(new RowSetEvent(this));
+ return status;
+ }
+
+ /**
+ * Positions the cursor to the current row. This is the row
+ * where the cursor was positioned before moving it to the insert
+ * row. If the cursor is not on the insert row, then this
+ * has no effect.
+ *
+ *
+ *
+ * @param concurrency The concurrency type.
+ **/
+ public void setConcurrency(int concurrency)
+ {
+ String property = "concurrency";
+ switch (concurrency)
+ {
+ case ResultSet.CONCUR_READ_ONLY: break;
+ case ResultSet.CONCUR_UPDATABLE: break;
+ default: throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+ }
+
+ Integer oldValue = new Integer(concurrency_);
+ Integer newValue = new Integer(concurrency);
+
+ concurrency_ = concurrency;
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ createNewStatement_ = true;
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "concurrency", concurrency);
+ }
+
+ //@A1A
+ /**
+ * Sets the JNDI naming context which provides name-to-object bindings
+ * and methods for retrieving and updating naming and directory services.
+ * If this is not set, a default InitialContext will be created.
+ * @param context A JNDI naming context.
+ **/
+ public void setContext(Context context)
+ {
+ String property = "context";
+ if (context == null)
+ throw new NullPointerException(property);
+
+ Context oldValue = getContext();
+ Context newValue = context;
+
+ context_ = context;
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets the name of the data source.
+ * Note: This property is not supported. The setDataSource method
+ * should be used for setting the data source.
+ * @param dataSourceName The data source name.
+ **/
+ public void setDataSourceName(String dataSourceName)
+ {
+ String property = "dataSourceName";
+ if (dataSourceName == null)
+ throw new NullPointerException(property);
+
+ String old = getDataSourceName();
+ dataSourceName_ = dataSourceName;
+ changes_.firePropertyChange(property, old, dataSourceName);
+ }
+
+ /**
+ * Sets the Date value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Date object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setDate(int parameterIndex, Date value) throws SQLException
+ {
+ validateStatement();
+ statement_.setDate(parameterIndex, value);
+ }
+
+ /**
+ * Sets the Date value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Date object.
+ * @param calendar The Calendar object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setDate(int parameterIndex, Date value, Calendar calendar) throws SQLException
+ {
+ validateStatement();
+ statement_.setDate(parameterIndex, value, calendar);
+ }
+
+ /**
+ * Sets the double value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The double value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setDouble(int parameterIndex, double value) throws SQLException
+ {
+ validateStatement();
+ statement_.setDouble(parameterIndex, value);
+ }
+
+ //@A2A
+ /**
+ * Sets the standard JNDI environment properties.
+ * If this is not set, a default set of properties will be used.
+ * @param environment A Hashtable of JNDI environment properties.
+ **/
+ public void setEnvironment(Hashtable environment)
+ {
+ String property = "enviroment";
+ if (environment == null)
+ throw new NullPointerException(property);
+
+ Hashtable oldValue = getEnvironment();
+ Hashtable newValue = environment;
+
+ environment_ = environment;
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets whether the escape scanning is enabled for escape substitution processing.
+ * @param enable true if enabled; false otherwise. The default value is true.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setEscapeProcessing(boolean enable) throws SQLException
+ {
+ Boolean old = new Boolean(getEscapeProcessing());
+
+ validateStatement();
+ statement_.setEscapeProcessing(enable);
+
+ escapeProcessing_ = enable; // save it, since it can't be retrieved anywhere else.
+
+ changes_.firePropertyChange("escapeProcessing", old, new Boolean(enable));
+ }
+
+ /**
+ * Sets the direction in which the rows in a result set are
+ * processed.
+ *
+ * @param fetchDirection 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 fetchDirection) throws SQLException
+ {
+ Integer old = new Integer(getFetchDirection());
+
+ if (resultSet_ != null)
+ resultSet_.setFetchDirection(fetchDirection);
+
+ validateStatement();
+ statement_.setFetchDirection(fetchDirection);
+
+ changes_.firePropertyChange("fetchDirection", old, new Integer(fetchDirection));
+ }
+
+
+ /**
+ * 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 maxFieldSize The maximum column size.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setMaxFieldSize(int maxFieldSize) throws SQLException
+ {
+ String property = "maxFieldSize";
+ validateStatement();
+
+ Integer oldValue = new Integer(getMaxFieldSize());
+ Integer newValue = new Integer(maxFieldSize);
+
+ statement_.setMaxFieldSize(maxFieldSize);
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets the maximum row limit for the rowset. The default value is zero indicating no maximum value.
+ * @param maxRows The maximum number of rows.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setMaxRows(int maxRows) throws SQLException
+ {
+ String property = "maxRows";
+ validateStatement();
+
+ Integer oldValue = new Integer(getMaxRows());
+ Integer newValue = new Integer(maxRows);
+
+ statement_.setMaxRows(maxRows);
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets the type at the specified parameterIndex to SQL NULL.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param sqlType The SQL type.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setNull(int parameterIndex, int sqlType) throws SQLException
+ {
+ validateStatement();
+ statement_.setNull(parameterIndex, sqlType);
+ }
+
+ /**
+ * Sets the user-named type or REF type at the specified parameterIndex to SQL NULL.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param sqlType The SQL type.
+ * @param typeName The fully qualified name of an SQL user-named type. This parameter is not used if the type is REF.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException
+ {
+ validateStatement();
+ statement_.setNull(parameterIndex, sqlType, typeName);
+ }
+
+ /**
+ * Sets the object value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Object value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setObject(int parameterIndex, Object value) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(parameterIndex, value);
+ }
+
+ /**
+ * Sets the object value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Object value.
+ * @param targetSqlType The SQL type.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setObject(int parameterIndex, Object value, int targetSqlType) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(parameterIndex, value, targetSqlType);
+ }
+
+ /**
+ * Sets the object value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Object value.
+ * @param targetSqlType The SQL type.
+ * @param scale The number of digits after the decimal point. This parameter is used only for SQL types Decimal or Numeric.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setObject(int parameterIndex, Object value, int targetSqlType, int scale) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(parameterIndex, value, targetSqlType, scale);
+ }
+
+ /**
+ * Sets the password used to make the connection.
+ * Note: This property has no effect unless the useDataSource property is set to false.
+ * @param password The password.
+ **/
+ public void setPassword(String password)
+ {
+ String property = "password";
+ if (password == null)
+ throw new NullPointerException(property);
+ validateConnection();
+
+ password_ = password;
+ changes_.firePropertyChange(property, "", password);
+ }
+
+ /**
+ * Sets the maximum wait time in seconds for a statement to execute.
+ * @param timeout The timeout value in seconds. The default value is zero indicating no maximum value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setQueryTimeout(int timeout) throws SQLException
+ {
+ String property = "timeout";
+ validateStatement();
+
+ Integer oldValue = new Integer(getQueryTimeout());
+ Integer newValue = new Integer(timeout);
+
+ statement_.setQueryTimeout(timeout);
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets whether the rowset is read-only. The default value is false indicating updates are allowed.
+ * @param readOnly true if read-only; false otherwise.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setReadOnly(boolean readOnly) throws SQLException
+ {
+ String property = "readOnly";
+
+ Boolean oldValue = new Boolean(isReadOnly());
+ Boolean newValue = new Boolean(readOnly);
+
+ if (connection_ != null)
+ connection_.setReadOnly(readOnly);
+ isReadOnly_ = readOnly;
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets Ref value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Ref object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setRef(int parameterIndex, Ref value) throws SQLException
+ {
+ validateStatement();
+ statement_.setRef(parameterIndex, value);
+ }
+
+ /**
+ * Sets the short value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The short value.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setShort(int parameterIndex, short value) throws SQLException
+ {
+ validateStatement();
+ statement_.setShort(parameterIndex, value);
+ }
+
+ /**
+ * Sets the string value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The String object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setString(int parameterIndex, String value) throws SQLException
+ {
+ validateStatement();
+ statement_.setString(parameterIndex, value);
+ }
+
+ /**
+ * Sets the time value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Time object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTime(int parameterIndex, Time value) throws SQLException
+ {
+ validateStatement();
+ statement_.setTime(parameterIndex, value);
+ }
+
+ /**
+ * Sets the time value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Time object.
+ * @param calendar The Calendar object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTime(int parameterIndex, Time value, Calendar calendar) throws SQLException
+ {
+ validateStatement();
+ statement_.setTime(parameterIndex, value, calendar);
+ }
+
+ /**
+ * Sets the timestamp value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Timestamp object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTimestamp(int parameterIndex, Timestamp value) throws SQLException
+ {
+ validateStatement();
+ statement_.setTimestamp(parameterIndex, value);
+ }
+
+ /**
+ * Sets the timestamp value at the specified parameterIndex.
+ * This parameter is used by the internal statement to populate the rowset via the execute method.
+ * @param parameterIndex The parameter index (1-based).
+ * @param value The Timestamp object.
+ * @param calendar The Calendar object.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTimestamp(int parameterIndex, Timestamp value, Calendar calendar) throws SQLException
+ {
+ validateStatement();
+ statement_.setTimestamp(parameterIndex, value, calendar);
+ }
+
+ /**
+ * Sets the transaction isolation level.
+ * @param level The transaction isolation level.
+ * Possible values are:
+ *
+ *
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTransactionIsolation(int level) throws SQLException
+ {
+ String property = "transactionIsolation";
+
+ Integer oldValue = new Integer(getTransactionIsolation());
+ Integer newValue = new Integer(level);
+
+ if (connection_ != null)
+ connection_.setTransactionIsolation(level);
+ transactionIsolation_ = level;
+
+ changes_.firePropertyChange(property, oldValue, newValue);
+ }
+
+ /**
+ * Sets the result set type.
+ * Valid values are:
+ *
+ *
+ * @param type The type.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setType(int type) throws SQLException
+ {
+ String property = "type";
+ switch (type)
+ {
+ case ResultSet.TYPE_FORWARD_ONLY: break;
+ case ResultSet.TYPE_SCROLL_INSENSITIVE: break;
+ case ResultSet.TYPE_SCROLL_SENSITIVE: break;
+ default: throw new ExtendedIllegalArgumentException(property, ExtendedIllegalArgumentException.RANGE_NOT_VALID);
+ }
+
+ Integer oldValue = new Integer(getType());
+ Integer newValue = new Integer(type_);
+
+ type_ = type;
+ changes_.firePropertyChange(property, oldValue, newValue);
+
+ createNewStatement_ = true;
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logProperty (this, property, type);
+ }
+
+ /**
+ * 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 map The type map.
+ * @exception SQLException If a database error occurs.
+ **/
+ public void setTypeMap(Map map) throws SQLException
+ {
+ if (map == null)
+ throw new NullPointerException("map");
+
+ if (connection_ != null)
+ connection_.setTypeMap(map);
+ typeMap_ = map;
+ }
+
+ /**
+ * Sets the URL used for getting a connection.
+ * Either this property or the dataSource property must be set before a connection can be made.
+ * This sets setUseDataSource to false.
+ * @param url The URL.
+ * @see #setUseDataSource
+ **/
+ public void setUrl(String url)
+ {
+ String property = "url";
+ if (url == null)
+ throw new NullPointerException(property);
+
+ validateConnection();
+
+ String old = getUrl();
+ url_ = url;
+ changes_.firePropertyChange(property, old, url);
+
+ useDataSource_ = false;
+
+ if (JDTrace.isTraceOn())
+ JDTrace.logProperty (this, property, url);
+ }
+
+ /**
+ * Sets whether the data source is used to make a connection to the database.
+ * @param useDataSource true if the data source is used; false if the URL is used.
+ * The default value is true.
+ **/
+ public void setUseDataSource(boolean useDataSource)
+ {
+ String property = "useDataSource";
+ validateConnection();
+
+ Boolean oldValue = new Boolean(isUseDataSource());
+ useDataSource_ = useDataSource;
+ changes_.firePropertyChange(property, oldValue, new Boolean(useDataSource) );
+ }
+
+ /**
+ * Sets the user name used to make the connection.
+ * Note: This property has no effect unless the useDataSource property is set to false.
+ * @param username The user name.
+ **/
+ public void setUsername(String username)
+ {
+ String property = "username";
+ if (username == null)
+ throw new NullPointerException(property);
+ validateConnection();
+
+ String old = getUsername();
+
+ username_ = username;
+ changes_.firePropertyChange(property, old, username);
+ }
+
+ /**
+ * Returns the name of the SQL cursor in use by the result set.
+ *
+ * @return The cursor name.
+ **/
+ public String toString ()
+ {
+ if (resultSet_ != null)
+ return resultSet_.toString();
+ else
+ return "";
+ }
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using an Array value.
+ DB2 for IBM i does not support arrays.
+
+ @param columnIndex The column index (1-based).
+ @param columnValue The column value or null if the value is SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support arrays.
+ @since Modification 5
+ **/
+ public void updateArray (int columnIndex, Array columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ //@G4A JDBC 3.0
+ /**
+ Updates a column in the current row using an Array value.
+ DB2 for IBM i does not support arrays.
+
+ @param columnName The column name.
+ @param columnValue The column value or null if the value is SQL NULL.
+
+ @exception SQLException Always thrown because DB2 for IBM i does not support arrays.
+ **/
+ public void updateArray (String columnName, Array columnValue)
+ throws SQLException
+ {
+ JDError.throwSQLException (JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+ /**
+ * Updates a column in the current row using 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.
+ *
+ * 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 parameterIndex of the first parameter is 1, the second is 2, ...
+ * @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 ; or if a database access error occurs
+ */
+ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
+ {
+ validateStatement();
+ statement_.setNCharacterStream(parameterIndex, value, 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 column 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; or if a database access error occurs
+ */
+ public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException
+ {
+ validateStatement();
+ statement_.setNCharacterStream(statement_.findParameterIndex(parameterName), value, length);
+ }
+
+ //@pda jdbc40
+ /**
+ * Sets the designated parameter to a java.sql.NClob
object. The driver converts this to a
+ * SQL NCLOB
value when it sends it to the database.
+ * @param parameterIndex of the first parameter is 1, the second is 2, ...
+ * @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 ; or if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void setNClob(int parameterIndex, NClob value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNClob(parameterIndex, value);
+ }
+/* endif */
+
+ //@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 column 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; or if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void setNClob(String parameterName, NClob value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNClob(statement_.findParameterIndex(parameterName), value);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Sets the designated parameter to the given String
object.
+ * The driver converts this to a SQL NCHAR
or
+ * NVARCHAR
or LONGNVARCHAR
value
+ * (depending on the argument's
+ * size relative to the driver's limits on NVARCHAR
values)
+ * when it sends it to the database.
+ *
+ * @param parameterIndex of the first parameter is 1, the second is 2, ...
+ * @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 ; or if a database access error occurs
+ */
+ public void setNString(int parameterIndex, String value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNString(parameterIndex, value);
+ }
+
+ //@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 column 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; or if a database access error occurs
+ */
+ public void setNString(String parameterName, String value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNString(statement_.findParameterIndex(parameterName), value);
+ }
+
+ //@pda jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.RowId
object. The
+ * driver converts this to a SQL ROWID
value when it sends it
+ * to the database
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ * @param x the parameter value
+ * @throws SQLException if a database access error occurs
+ */
+/* ifdef JDBC40 */
+ public void setRowId(int parameterIndex, RowId x) throws SQLException
+ {
+ validateStatement();
+ statement_.setRowId(parameterIndex, x);
+ }
+/* endif */
+
+ //@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
+ */
+/* ifdef JDBC40 */
+ public void setRowId(String parameterName, RowId x) throws SQLException
+ {
+ validateStatement();
+ statement_.setRowId(statement_.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 parameterIndex index of the first parameter is 1, the second is 2, ...
+ * @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 result set,
+ * Writer
or OutputStream
has not been closed
+ * for the SQLXML
object or
+ * if there is an error processing the XML value. The getCause
method
+ * of the exception may provide a more detailed exception, for example, if the
+ * stream does not contain valid XML.
+ */
+/* ifdef JDBC40 */
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
+ {
+ validateStatement();
+ statement_.setSQLXML(parameterIndex, xmlObject);
+ }
+/* 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 result set,
+ * Writer
or OutputStream
has not been closed
+ * for the SQLXML
object or
+ * if there is an error processing the XML value. The getCause
method
+ * of the exception may provide a more detailed exception, for example, if the
+ * stream does not contain valid XML.
+ */
+/* ifdef JDBC40 */
+ public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException
+ {
+ validateStatement();
+ statement_.setSQLXML(statement_.findParameterIndex(parameterName), xmlObject);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Retrieves the holdability of this RowSet
object
+ * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT
or ResultSet.CLOSE_CURSORS_AT_COMMIT
+ * The holdability is derived in this order of precedence:
+
+
+ Full functionality of #1 and #2 requires OS/400 v5r2
+ or IBM i. If connecting to OS/400 V5R1 or earlier,
+ the value specified on these two methods will be ignored and the default holdability
+ will be the value of #3.
+ * @throws SQLException if a database error occurs
+ */
+/* ifdef JDBC40 */
+ public int getHoldability() throws SQLException
+ {
+ return resultSet_.getHoldability();
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Retrieves the value of the designated column in the current row
+ * of this cursor hold
+ driver property.ResultSet
object as a
+ * java.io.Reader
object.
+ * It is intended for use when
+ * accessing NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * @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 columnIndex the first column is 1, the second is 2, ...
+ * @exception SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public Reader getNCharacterStream(int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNCharacterStream(columnIndex);
+ }
+
+ //@pda jdbc40
+ /**
+ * Retrieves the value of the designated column in the current row
+ * of this ResultSet
object as a
+ * java.io.Reader
object.
+ * It is intended for use when
+ * accessing NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @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
+ * @exception SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public Reader getNCharacterStream(String columnLabel) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNCharacterStream(columnLabel);
+ }
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column is 1, the second is 2, ...
+ * @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; this method is called on a closed result set
+ * or if a database access error occurs
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public NClob getNClob(int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNClob(columnIndex);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the 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; this method is called on a closed result set
+ * or if a database access error occurs
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public NClob getNClob(String columnLabel) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNClob(columnLabel);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column is 1, the second is 2, ...
+ * @return the column value; if the value is SQL NULL
, the
+ * value returned is null
+ * @exception SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public String getNString(int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNString(columnIndex);
+ }
+
+ //@pda jdbc40
+ /**
+ * 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 columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @return the column value; if the value is SQL NULL
, the
+ * value returned is null
+ * @exception SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public String getNString(String columnLabel) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getNString(columnLabel);
+ }
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column is 1, the second 2, ...
+ * @return the column value; if the value is a SQL NULL
the
+ * value returned is null
+ * @throws SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public RowId getRowId(int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getRowId(columnIndex);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @return the column value ; if the value is a SQL NULL
the
+ * value returned is null
+ * @throws SQLException if a database access error occurs
+ * or this method is called on a closed result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public RowId getRowId(String columnLabel) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getRowId(columnLabel);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column 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 result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML(int columnIndex) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getSQLXML(columnIndex);
+ }
+/* endif */
+
+ //@pda jdbc40
+
+ /**
+ * 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 columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @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 result set
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML(String columnLabel) throws SQLException
+ {
+ validateResultSet();
+ return resultSet_.getSQLXML(columnLabel);
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Retrieves whether this ResultSet
object has been closed. A ResultSet
is closed if the
+ * method close has been called on it, or if it is automatically closed.
+ *
+ * @return true if this ResultSet
object is closed; false if it is still open
+ * @throws SQLException if a database access error occurs
+ */
+ public boolean isClosed() throws SQLException
+ {
+ return resultSet_.isClosed();
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with an ascii stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream (columnIndex, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with an ascii stream value, which will have
+ * the specified number of bytes..
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream (columnLabel, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a binary stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream(columnIndex, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a binary stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream(columnLabel, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @param length the number of bytes in the parameter data.
+ * @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 updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob (columnIndex, inputStream, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @param length the number of bytes in the parameter data.
+ * @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 updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob(columnLabel, inputStream, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream(columnIndex, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream(columnLabel, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @param reader An object that contains the data to set the parameter value to.
+ * @param length the number of characters in the parameter data.
+ * @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 updateClob(int columnIndex, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob(columnIndex, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @param length the number of characters in the parameter data.
+ * @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 updateClob(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob(columnLabel, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNCharacterStream(columnIndex, x, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a character stream value, which will have
+ * the specified number of bytes. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * 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
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNCharacterStream(columnLabel, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.NClob
value.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @param nClob 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; 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 columnIndex, NClob nClob) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnIndex, nClob);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.NClob
value.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param nClob 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; 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 columnLabel, NClob nClob) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnLabel, nClob);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @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 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 columnIndex, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnIndex, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column using 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.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @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 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 columnLabel, Reader reader, long length) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnLabel, reader, length);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a String
value.
+ * It is intended for use when updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @param nString 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; this method is called on a closed result set,
+ * the result set concurrency is CONCUR_READ_ONLY
+ * or if a database access error occurs
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNString(int columnIndex, String nString) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNString (columnIndex, nString);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a String
value.
+ * It is intended for use when updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * The updater methods are used to update column values in the
+ * current row or the insert row. The updater methods do not
+ * update the underlying database; instead the updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param nString 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; this method is called on a closed result set;
+ * the result set concurrency is CONCUR_READ_ONLY
+ * or if a database access error occurs
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void updateNString(String columnLabel, String nString) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNString (columnLabel, nString);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a RowId
value. The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @param x the 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
+ */
+/* ifdef JDBC40 */
+ public void updateRowId(int columnIndex, RowId x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateRowId(columnIndex, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a RowId
value. The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param x the 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
+ */
+/* ifdef JDBC40 */
+ public void updateRowId(String columnLabel, RowId x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateRowId(columnLabel, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.SQLXML
value.
+ * The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ * java.xml.transform.Result
,
+ * Writer
or OutputStream
has not been closed
+ * for the SQLXML
object,
+ * if there is an error processing the XML value or
+ * the result set concurrency is CONCUR_READ_ONLY
. The getCause
method
+ * of the exception may provide a more detailed exception, for example, if the
+ * stream does not contain valid XML.
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateSQLXML(columnIndex, xmlObject);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * Updates the designated column with a java.sql.SQLXML
value.
+ * The updater
+ * methods are used to update column values in the current row or the insert
+ * row. The updater methods do not update the underlying database; instead
+ * the updateRow
or insertRow
methods are called
+ * to update the database.
+ * java.xml.transform.Result
,
+ * Writer
or OutputStream
has not been closed
+ * for the SQLXML
object,
+ * if there is an error processing the XML value or
+ * the result set concurrency is CONCUR_READ_ONLY
. The getCause
method
+ * of the exception may provide a more detailed exception, for example, if the
+ * stream does not contain valid XML.
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+/* ifdef JDBC40 */
+ public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateSQLXML(columnLabel, xmlObject);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+/* endif */
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "com.ibm.as400.access.AS400JDBCRowSet", "javax.sql.RowSet" };
+ }
+
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter in this RowSet
object's command
+ * 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.
+ *
+ * setAsciiStream
which takes a length parameter.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ * @param x the Java input stream that contains the ASCII parameter value
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
+ {
+ validateStatement();
+ statement_.setAsciiStream(parameterIndex, x);
+ }
+
+ //@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.
+ *
+ * CallableStatement
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setAsciiStream(statement_.findParameterIndex(parameterName), x, length);
+ }
+
+ //@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.
+ *
+ * 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 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
+ {
+ validateStatement();
+ statement_.setAsciiStream(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given
+ * java.math.BigDecimal
value.
+ * The driver converts this to an SQL NUMERIC
value when
+ * it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getBigDecimal
+ */
+ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException
+ {
+ validateStatement();
+ statement_.setBigDecimal(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter in this RowSet
object's command
+ * 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.
+ *
+ * setBinaryStream
which takes a length parameter.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ * @param x the java input stream which contains the binary parameter value
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
+ {
+ validateStatement();
+ statement_.setBinaryStream(parameterIndex, x);
+ }
+
+ //@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.
+ *
+ * CallableStatement
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setBinaryStream(statement_.findParameterIndex(parameterName), x, length);
+ }
+
+ //@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.
+ *
+ * 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 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
+ {
+ validateStatement();
+ statement_.setBinaryStream(statement_.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 PreparedStatement
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 server 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 server as a LONGVARBINARY
or a BLOB
+ * @param parameterIndex index of the first parameter is 1,
+ * the second is 2, ...
+ * @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 a database access error occurs,
+ * this method is called on a closed PreparedStatement
,
+ * if parameterIndex does not correspond
+ * to a parameter marker in the SQL statement, if the length specified
+ * is less than zero or if the number of bytes in the inputstream does not match
+ * the specfied length.
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ *
+ */
+ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
+ {
+ validateStatement();
+ statement_.setBlob(parameterIndex, inputStream, length);
+ }
+
+ //@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 server 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 server as a LONGVARBINARY
or a BLOB
+ *
+ * setBlob
which takes a length parameter.
+ *
+ * @param parameterIndex index of the first parameter is 1,
+ * the second is 2, ...
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @throws SQLException if a database access error occurs,
+ * this method is called on a closed PreparedStatement
or
+ * if parameterIndex does not correspond
+ * to a parameter marker in the SQL statement,
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ *
+ */
+ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
+ {
+ validateStatement();
+ statement_.setBlob(parameterIndex, inputStream);
+ }
+
+ //@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
+ {
+ validateStatement();
+ statement_.setBlob(statement_.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 server 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 server as a LONGVARBINARY
or a BLOB
+ *
+ * @param parameterName the name of the parameter to be set
+ * the second is 2, ...
+ *
+ * @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
+ {
+ validateStatement();
+ statement_.setBlob(statement_.findParameterIndex(parameterName), inputStream, length);
+ }
+
+ //@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 server 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 send to the server as a LONGVARBINARY
or a BLOB
+ *
+ * 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 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
+ {
+ validateStatement();
+ statement_.setBlob(statement_.findParameterIndex(parameterName), inputStream);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java boolean
value.
+ * The driver converts this
+ * to an SQL BIT
or BOOLEAN
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed CallableStatement
+ * @see #getBoolean
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ */
+ public void setBoolean(String parameterName, boolean x) throws SQLException
+ {
+ validateStatement();
+ statement_.setBoolean(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java byte
value.
+ * The driver converts this
+ * to an SQL TINYINT
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getByte
+ */
+ public void setByte(String parameterName, byte x) throws SQLException
+ {
+ validateStatement();
+ statement_.setByte(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java array of bytes.
+ * The driver converts this to an SQL VARBINARY
or
+ * LONGVARBINARY
(depending on the argument's size relative
+ * to the driver's limits on VARBINARY
values) when it sends
+ * it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getBytes
+ */
+ public void setBytes(String parameterName, byte[] x) throws SQLException
+ {
+ validateStatement();
+ statement_.setBytes(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter in this RowSet
object's command
+ * 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.
+ *
+ * setCharacterStream
which takes a length parameter.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ * @param reader the java.io.Reader
object that contains the
+ * Unicode data
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
+ {
+ validateStatement();
+ statement_.setCharacterStream(parameterIndex, reader);
+ }
+
+ //@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.
+ *
+ * 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, int length) throws SQLException
+ {
+ validateStatement();
+ statement_.setCharacterStream(statement_.findParameterIndex(parameterName), reader, length);
+ }
+
+ //@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.
+ *
+ * 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 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
+ {
+ validateStatement();
+ statement_.setCharacterStream(statement_.findParameterIndex(parameterName), reader);
+ }
+
+ //@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 PreparedStatement
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 server 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 server as a LONGVARCHAR
or a CLOB
+ * @param parameterIndex index of the first parameter is 1, the second is 2, ...
+ * @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 a database access error occurs, this method is called on
+ * a closed PreparedStatement
, if parameterIndex does not correspond to a parameter
+ * marker in the SQL statement, or if the length specified is less than zero.
+ *
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this metho
+ */
+ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
+ {
+ validateStatement();
+ statement_.setClob(parameterIndex, reader, length);
+ }
+
+ //@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 server 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 server as a LONGVARCHAR
or a CLOB
+ *
+ * setClob
which takes a length parameter.
+ *
+ * @param parameterIndex index of the first parameter is 1, the second is 2, ...
+ * @param reader An object that contains the data to set the parameter value to.
+ * @throws SQLException if a database access error occurs, this method is called on
+ * a closed PreparedStatement
or if parameterIndex does not correspond to a parameter
+ * marker in the SQL statement
+ *
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setClob(int parameterIndex, Reader reader) throws SQLException
+ {
+ validateStatement();
+ statement_.setClob(parameterIndex, reader);
+ }
+
+ //@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
+ {
+ validateStatement();
+ statement_.setClob(statement_.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 server 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 send to the server 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
+ {
+ validateStatement();
+ statement_.setClob(statement_.findParameterIndex(parameterName), reader, length);
+ }
+
+ //@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 server 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 send to the server as a LONGVARCHAR
or a CLOB
+ *
+ * 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 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
+ {
+ validateStatement();
+ statement_.setClob(statement_.findParameterIndex(parameterName), reader);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Date
value,
+ * using the given Calendar
object. The driver uses
+ * the Calendar
object to construct an SQL DATE
value,
+ * which the driver then sends to the database. With a
+ * a Calendar
object, the driver can calculate the date
+ * taking into account a custom timezone. If no
+ * Calendar
object is specified, the driver uses the default
+ * timezone, which is that of the virtual machine running the application.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter value
+ * @param cal the Calendar
object the driver will use
+ * to construct the date
+ * @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 #getDate
+ */
+ public void setDate(String parameterName, Date x, Calendar cal) throws SQLException
+ {
+ validateStatement();
+ statement_.setDate(statement_.findParameterIndex(parameterName), x, cal);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Date
value
+ * using the default time zone of the virtual machine that is running
+ * the application.
+ * The driver converts this
+ * to an SQL DATE
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getDate
+ */
+ public void setDate(String parameterName, Date x) throws SQLException
+ {
+ validateStatement();
+ statement_.setDate(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java double
value.
+ * The driver converts this
+ * to an SQL DOUBLE
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getDouble
+ */
+ public void setDouble(String parameterName, double x) throws SQLException
+ {
+ validateStatement();
+ statement_.setDouble(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java float
value.
+ * The driver converts this
+ * to an SQL FLOAT
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getFloat
+ */
+ public void setFloat(String parameterName, float x) throws SQLException
+ {
+ validateStatement();
+ statement_.setFloat(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java int
value.
+ * The driver converts this
+ * to an SQL INTEGER
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getInt
+ */
+ public void setInt(String parameterName, int x) throws SQLException
+ {
+ validateStatement();
+ statement_.setInt(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java long
value.
+ * The driver converts this
+ * to an SQL BIGINT
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getLong
+ */
+ public void setLong(String parameterName, long x) throws SQLException
+ {
+ validateStatement();
+ statement_.setLong(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter in this RowSet
object's command
+ * 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.
+
+ * setNCharacterStream
which takes a length parameter.
+ *
+ * @param parameterIndex of the first parameter is 1, the second is 2, ...
+ * @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 PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNCharacterStream(parameterIndex, value);
+ }
+
+ //@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.
+
+ * setNCharacterStream
which takes a length parameter.
+ *
+ * @param parameterName the name of the parameter
+ * @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
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setNCharacterStream(String parameterName, Reader value) throws SQLException
+ {
+ validateStatement();
+ statement_.setNCharacterStream(statement_.findParameterIndex(parameterName), value);
+ }
+
+ //@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 PreparedStatement
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 server 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 server as a LONGNVARCHAR
or a NCLOB
+ * @param parameterIndex index of the first parameter is 1, the second is 2, ...
+ * @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 PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ *
+ */
+ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
+ {
+ validateStatement();
+ statement_.setNClob(parameterIndex, reader, length);
+ }
+
+ //@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 server 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 server as a LONGNVARCHAR
or a NCLOB
+ * setNClob
which takes a length parameter.
+ *
+ * @param parameterIndex index of the first parameter is 1, the second is 2, ...
+ * @param reader An object that contains the data to set the parameter value to.
+ * @throws SQLException if parameterIndex does not correspond to a parameter
+ * marker in the SQL statement;
+ * 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 PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ *
+ */
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException
+ {
+ validateStatement();
+ statement_.setNClob(parameterIndex, reader);
+ }
+
+ //@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 server 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 send to the server 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
+ {
+ validateStatement();
+ statement_.setNClob(statement_.findParameterIndex(parameterName), reader, length);
+ }
+
+ //@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 server 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 send to the server as a LONGNVARCHAR
or a NCLOB
+ * 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 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
+ {
+ validateStatement();
+ statement_.setNClob(statement_.findParameterIndex(parameterName), reader);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to SQL NULL
.
+ * This version of the method setNull
should
+ * be used for user-defined types and REF type parameters. Examples
+ * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
+ * named array types.
+ *
+ * java.sql.Types
+ * @param typeName the fully-qualified name of an SQL user-defined type;
+ * ignored if the parameter is not a user-defined type or
+ * SQL REF
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 setNull(String parameterName, int sqlType, String typeName) throws SQLException
+ {
+ validateStatement();
+ statement_.setNull(statement_.findParameterIndex(parameterName), sqlType, typeName);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to SQL NULL
.
+ *
+ * java.sql.Types
+ * @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 setNull(String parameterName, int sqlType) throws SQLException
+ {
+ validateStatement();
+ statement_.setNull(statement_.findParameterIndex(parameterName), sqlType);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the value of the designated parameter with the given object. The second
+ * argument must be an object type; for integral values, the
+ * java.lang
equivalent objects should be used.
+ *
+ * SQLData
),
+ * the JDBC driver should call the method SQLData.writeSQL
to write it
+ * to the SQL data stream.
+ * If, on the other hand, the object is of a class implementing
+ * Ref
, Blob
, Clob
, NClob
,
+ * Struct
, java.net.URL
,
+ * or Array
, the driver should pass it to the database as a
+ * value of the corresponding SQL type.
+ * CallableStatement
+ * @exception SQLFeatureNotSupportedException if targetSqlType
is
+ * a ARRAY
, BLOB
, CLOB
,
+ * DATALINK
, JAVA_OBJECT
, NCHAR
,
+ * NCLOB
, NVARCHAR
, LONGNVARCHAR
,
+ * REF
, ROWID
, SQLXML
+ * or STRUCT
data type and the JDBC driver does not support
+ * this data type
+ * @see Types
+ * @see #getObject
+ */
+ public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(statement_.findParameterIndex(parameterName), x, targetSqlType, scale);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the value of the designated parameter with the given object.
+ * This method is like the method setObject
+ * above, except that it assumes a scale of zero.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the object containing the input parameter value
+ * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
+ * sent to the database
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed CallableStatement
+ * @exception SQLFeatureNotSupportedException if targetSqlType
is
+ * a ARRAY
, BLOB
, CLOB
,
+ * DATALINK
, JAVA_OBJECT
, NCHAR
,
+ * NCLOB
, NVARCHAR
, LONGNVARCHAR
,
+ * REF
, ROWID
, SQLXML
+ * or STRUCT
data type and the JDBC driver does not support
+ * this data type
+ * @see #getObject
+ */
+ public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(statement_.findParameterIndex(parameterName), x, targetSqlType);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the value of the designated parameter with the given object.
+ * The second parameter must be of type Object
; therefore, the
+ * java.lang
equivalent objects should be used for built-in types.
+ *
+ * Object
types to SQL types. The given argument
+ * will be converted to the corresponding SQL type before being
+ * sent to the database.
+ *
+ * SQLData
,
+ * the JDBC driver should call the method SQLData.writeSQL
+ * to write it to the SQL data stream.
+ * If, on the other hand, the object is of a class implementing
+ * Ref
, Blob
, Clob
, NClob
,
+ * Struct
, java.net.URL
,
+ * or Array
, the driver should pass it to the database as a
+ * value of the corresponding SQL type.
+ * CallableStatement
or if the given
+ * Object
parameter is ambiguous
+ * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
+ * this method
+ * @see #getObject
+ */
+ public void setObject(String parameterName, Object x) throws SQLException
+ {
+ validateStatement();
+ statement_.setObject(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java short
value.
+ * The driver converts this
+ * to an SQL SMALLINT
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getShort
+ */
+ public void setShort(String parameterName, short x) throws SQLException
+ {
+ validateStatement();
+ statement_.setShort(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given Java String
value.
+ * The driver converts this
+ * to an SQL VARCHAR
or LONGVARCHAR
value
+ * (depending on the argument's
+ * size relative to the driver's limits on VARCHAR
values)
+ * when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getString
+ */
+ public void setString(String parameterName, String x) throws SQLException
+ {
+ validateStatement();
+ statement_.setString(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Time
value,
+ * using the given Calendar
object. The driver uses
+ * the Calendar
object to construct an SQL TIME
value,
+ * which the driver then sends to the database. With a
+ * a Calendar
object, the driver can calculate the time
+ * taking into account a custom timezone. If no
+ * Calendar
object is specified, the driver uses the default
+ * timezone, which is that of the virtual machine running the application.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter value
+ * @param cal the Calendar
object the driver will use
+ * to construct the time
+ * @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 #getTime
+ */
+ public void setTime(String parameterName, Time x, Calendar cal) throws SQLException
+ {
+ validateStatement();
+ statement_.setTime(statement_.findParameterIndex(parameterName), x, cal);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Time
value.
+ * The driver converts this
+ * to an SQL TIME
value when it sends it to the database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getTime
+ */
+ public void setTime(String parameterName, Time x) throws SQLException
+ {
+ validateStatement();
+ statement_.setTime(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Timestamp
value,
+ * using the given Calendar
object. The driver uses
+ * the Calendar
object to construct an SQL TIMESTAMP
value,
+ * which the driver then sends to the database. With a
+ * a Calendar
object, the driver can calculate the timestamp
+ * taking into account a custom timezone. If no
+ * Calendar
object is specified, the driver uses the default
+ * timezone, which is that of the virtual machine running the application.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter value
+ * @param cal the Calendar
object the driver will use
+ * to construct the timestamp
+ * @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 #getTimestamp
+ */
+ public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException
+ {
+ validateStatement();
+ statement_.setTimestamp(statement_.findParameterIndex(parameterName), x, cal);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.sql.Timestamp
value.
+ * The driver
+ * converts this to an SQL TIMESTAMP
value when it sends it to the
+ * database.
+ *
+ * @param parameterName the name of the parameter
+ * @param x the parameter 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 #getTimestamp
+ */
+ public void setTimestamp(String parameterName, Timestamp x) throws SQLException
+ {
+ validateStatement();
+ statement_.setTimestamp(statement_.findParameterIndex(parameterName), x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Sets the designated parameter to the given java.net.URL
value.
+ * The driver converts this to an SQL DATALINK
value
+ * when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ * @param x the java.net.URL
object to be set
+ * @exception SQLException if a database access error occurs or
+ * this method is called on a closed PreparedStatement
+ * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
+ */
+ public void setURL(int parameterIndex, URL x) throws SQLException
+ {
+ validateStatement();
+ statement_.setURL(parameterIndex, x);
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with an ascii stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateAsciiStream
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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 updateAsciiStream(int columnIndex, InputStream x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream (columnIndex, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with an ascii stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateAsciiStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param x the new column value
+ * @exception SQLException if the columnLabel 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 updateAsciiStream(String columnLabel, InputStream x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateAsciiStream (columnLabel, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a binary stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBinaryStream
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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 updateBinaryStream(int columnIndex, InputStream x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream(columnIndex, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a binary stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBinaryStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param x the new column value
+ * @exception SQLException if the columnLabel 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 updateBinaryStream(String columnLabel, InputStream x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBinaryStream(columnLabel, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * 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.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBlob
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @param inputStream 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 columnIndex, InputStream inputStream) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob(columnIndex, inputStream);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * 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.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateBlob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param inputStream An object that contains the data to set the parameter
+ * value to.
+ * @exception SQLException if the columnLabel 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 columnLabel, InputStream inputStream) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateBlob(columnLabel, inputStream);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateCharacterStream
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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 updateCharacterStream(int columnIndex, Reader x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream(columnIndex, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateCharacterStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * the new column value
+ * @exception SQLException if the columnLabel 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 updateCharacterStream(String columnLabel, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateCharacterStream (columnLabel, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateClob
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @param reader 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 updateClob(int columnIndex, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob(columnIndex, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateClob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @exception SQLException if the columnLabel 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 updateClob(String columnLabel, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateClob (columnLabel, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNCharacterStream
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second is 2, ...
+ * @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 columnIndex, Reader x) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNCharacterStream (columnIndex, x);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column with a character stream value.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The
+ * driver does the necessary conversion from Java character format to
+ * the national character set in the database.
+ * It is intended for use when
+ * updating NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNCharacterStream
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader the java.io.Reader
object containing
+ * the new column value
+ * @exception SQLException if the columnLabel 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 columnLabel, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNCharacterStream (columnLabel, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ *
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNClob
which takes a length parameter.
+ *
+ * @param columnIndex the first column is 1, the second 2, ...
+ * @param reader 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 columnIndex, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnIndex, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ //@PDA jdbc40
+ /**
+ * Updates the designated column using the given Reader
+ * object.
+ * The data will be read from the stream
+ * as needed until end-of-stream is reached. The JDBC driver will
+ * do any necessary conversion from UNICODE to the database char format.
+ *
+ * updateRow
or
+ * insertRow
methods are called to update the database.
+ *
+ * updateNClob
which takes a length parameter.
+ *
+ * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, then the label is the name of the column
+ * @param reader An object that contains the data to set the parameter value to.
+ * @throws SQLException if the columnLabel 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 columnLabel, Reader reader) throws SQLException
+ {
+ validateResultSet();
+ resultSet_.updateNClob(columnLabel, reader);
+
+ eventSupport_.fireRowChanged(new RowSetEvent(this));
+ }
+
+ public Object getObject(int columnIndex, Class type) throws SQLException {
+ validateResultSet();
+ return resultSet_.getObject(columnIndex, type);
+ }
+
+ public Object getObject(String columnLabel, Class type)
+ throws SQLException {
+ validateResultSet();
+ return resultSet_.getObject(columnLabel, type);
+
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCSQLXML.java b/jdbc40/com/ibm/as400/access/AS400JDBCSQLXML.java
new file mode 100644
index 000000000..1f58a3a09
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCSQLXML.java
@@ -0,0 +1,1235 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCSQLXML.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) 2006-2006 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+/* endif */
+
+/* ifdef JDBC40 */
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Result;
+/* endif */
+/* ifdef JDBC40 */
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+/* endif */
+/* ifdef JDBC40 */
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXResult;
+import javax.xml.transform.stax.StAXSource;
+import org.xml.sax.InputSource;
+import javax.xml.parsers.ParserConfigurationException;
+/* endif */
+
+/* ifdef JDBC40 */
+import org.xml.sax.SAXException;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSSerializer;
+/* endif */
+//@PDA jdbc40 new class
+//@xml2 whole class is redesigned after that of The Native Driver
+/**
+This class provides the object interface for using XML data through JDBC.
+The mapping in the Java programming language for the SQL XML type.
+XML is a built-in type that stores an XML value as a column value in a row of a database table.
+The SQLXML interface provides methods for accessing the XML value as a String, a Reader or Writer, or as a Stream.
+This class returns the data as an XML type. The actual type on the host may vary.
+Instances of this class are created by AS400JDBCConnection.
+This class should not be used if JDK 1.6 is not in use.
+**/
+public class AS400JDBCSQLXML
+/* ifdef JDBC40 */
+implements SQLXML
+/* endif */
+
+{
+
+ static final int MAX_XML_SIZE = AS400JDBCDatabaseMetaData.MAX_LOB_LENGTH; //@xml3
+ // We may internally store the SQLXML object as a DOM document
+ // if getResult was used to create the object
+ static final int DOM_DOCUMENT = 22345;
+ static final int LOB_FREED = 0;
+ int lobType = LOB_FREED; //corresponding to SQLData numbers
+
+ AS400JDBCClob clobValue_ = null;
+ AS400JDBCBlob blobValue_ = null;
+ AS400JDBCClobLocator clobLocatorValue_ = null;
+ AS400JDBCBlobLocator blobLocatorValue_ = null;
+
+ /* Document available in JDK 1.4, so this cannot be moved back to */
+ /* V5R4 which still supports JDK 1.3. In V5R4, this will need to */
+ /* be JDBC 4.0 only */
+ org.w3c.dom.Document domDocument_ = null;
+
+ //Today, the only case where isXML_ can be true is if this is a AS400JDBCSQLXMLLocator
+ //(since xml columns are always returned as locators from hostserver)
+ protected boolean isXML_ = false; //@xml4 true if this data originated from a native XML column type
+
+ /**
+ * Constructs an AS400JDBCSQLXML object. This is only a dummy constructor used by subclasses.
+ */
+ protected AS400JDBCSQLXML()
+ {
+ }
+
+ /**
+ * Constructs an AS400JDBCSQLXML object. The data is contained
+ * in the String. No further communication with the IBM i system is necessary.
+ *
+ * @param data The SQLXML data.
+ * @param maxLength Max length.
+ * @throws SQLException
+ */
+ AS400JDBCSQLXML(String data, int maxLength) throws SQLException
+ {
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+
+ // We must make sure the the data is well formed XML data. Otherwise it is not valid
+ // and we should throw a data type mismatch error.
+ // For simplicity's sake, just check for an opening <
+ data = data.trim();
+ if ((data.length() == 0) || (data.charAt(0) != '<')) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ lobType = SQLData.CLOB;
+ clobValue_ = new AS400JDBCClob(data, maxLength, isXML_); //@xmltrim
+
+ }
+
+ /**
+ * Constructs an empty AS400JDBCSQLXML object.
+ * No further communication with the IBM i system is necessary.
+ *
+ * @param data The SQLXML data.
+ * @param maxLength Max length.
+ * @throws SQLException
+ */
+ AS400JDBCSQLXML(int maxLength) throws SQLException
+ {
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+ String data ="";
+
+ lobType = SQLData.CLOB;
+ clobValue_ = new AS400JDBCClob(data, maxLength, isXML_); //@xmltrim
+
+ }
+
+
+ /**
+ * Constructs an AS400JDBCSQLXML object. The data is contained
+ * in the String. No further communication with the IBM i system is necessary.
+ *
+ * @param data The SQLXML data.
+ * @throws SQLException
+ */
+ AS400JDBCSQLXML(String data) throws SQLException
+ {
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+
+ // We must make sure the the data is well formed XML data. Otherwise it is not valid
+ // and we should throw a data type mismatch error.
+ // For simplicity's sake, just check for an opening <
+ data = data.trim();
+ if ((data.length() == 0) || (data.charAt(0) != '<')) {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ }
+
+
+
+ lobType = SQLData.CLOB;
+ clobValue_ = new AS400JDBCClob(data, AS400JDBCClob.MAX_LOB_SIZE, isXML_); //@xmltrim
+
+ }
+
+ /**
+ * Constructs an AS400JDBCSQLXML object. The data is contained
+ * in the String. No further communication with the IBM i system is necessary.
+ *
+ * @param data The SQLXML data.
+ */
+ AS400JDBCSQLXML(char[] data)
+ {
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+
+ lobType = SQLData.CLOB;
+ clobValue_ = new AS400JDBCClob(data, isXML_); //@xmltrim
+ }
+
+
+ /**
+ * Constructs an AS400JDBCSQLXML object. The data is contained
+ * in the array. No further communication with the IBM i system is necessary.
+ * This constructor is used for returning blob data in an XML object.
+ *
+ * @param data The SQLXML data.
+ * @param maxLength Max length.
+ */
+ AS400JDBCSQLXML (byte [] data, long maxLength)
+ {
+ isXML_ = true;//@xmltrim (match native jdbc for trimming xml decl if using sqlxml)
+
+ lobType = SQLData.BLOB;
+ blobValue_ = new AS400JDBCBlob(data, (int)maxLength);
+ }
+
+
+ /**
+ * Retrieves the XML value designated by this SQLXML instance as a java.io.Reader object.
+ * The format of this stream is defined by org.xml.sax.InputSource,
+ * where the characters in the stream represent the Unicode code points for
+ * XML according to section 2 and appendix B of the XML 1.0 specification.
+ * Although an encoding declaration other than Unicode may be present,
+ * the encoding of the stream is Unicode.
+ * The behavior of this method is the same as ResultSet.getCharacterStream()
+ * when the designated column of the ResultSet has a type java.sql.Types of SQLXML.
+ * SQLXML
object.
+ * @return a String that is the string representation of the XML value
+ * @throws SQLException if there is an error accessing the XML value
+ */
+ public synchronized String getString() throws SQLException
+ {
+ String s = null;
+
+ switch (lobType)
+ {
+ case SQLData.DBCLOB:
+ case SQLData.CLOB:
+ s = clobValue_.getSubString((long) 1, (int) clobValue_.length());
+ break;
+ case SQLData.DBCLOB_LOCATOR:
+ case SQLData.CLOB_LOCATOR:
+ s = clobLocatorValue_.getSubString((long) 1, (int) clobLocatorValue_.length());
+ break;
+ case SQLData.BLOB:
+ case SQLData.BLOB_LOCATOR:
+
+ // Check for a byte order mark
+ String encoding;
+ int byteOrderMarkSize = 0;
+ byte[] bytes = null;
+ if (lobType == SQLData.BLOB)
+ {
+ if(blobValue_.length() > 4)//@xmlzero
+ bytes = blobValue_.getBytes(1, 4);
+ else
+ bytes = new byte[0]; //@xmlzero
+
+ } else
+ {
+ InputStream is = blobLocatorValue_.getBinaryStream();
+ bytes = new byte[4];
+ try
+ {
+ int bytesRead = is.read(bytes);
+ if (bytesRead == 0)
+ bytes = new byte[0];
+ } catch (Exception e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+ return null;
+ }finally
+ {
+ try{
+ is.close();
+ }catch(Exception e){
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logException(this, "is.close() exception", e);
+ }
+ }
+ }
+ }
+ if (bytes.length < 4)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+ if ((bytes[0] == (byte) 0xEF) && (bytes[1] == (byte) 0xBB)
+ && (bytes[2] == (byte) 0xBF))
+ {
+ encoding = "UTF-8";
+ byteOrderMarkSize = 3;
+ } else if ((bytes[0] == (byte) 0xFE)
+ && (bytes[1] == (byte) 0xFF))
+ {
+ encoding = "UTF-16BE";
+ byteOrderMarkSize = 2;
+ } else if ((bytes[0] == (byte) 0xFF)
+ && (bytes[1] == (byte) 0xFE))
+ {
+ encoding = "UTF-16LE";
+ byteOrderMarkSize = 2;
+ } else
+ {
+ // We don't support the UCS-4 variants. In the future, we
+ // may need to.
+
+ // In this case we need to peek at the stream to determine
+ // which format it is in.
+ // At a minimum, we expect it to begin with '<' (after
+ // ignoring possible white space)
+ //
+ int position = 1;
+ byte nonWhiteSpaceByte = 0x20;
+ int i = 0;
+ while (nonWhiteSpaceByte == 0x20)
+ {
+ // Get the first few bytes of the blob in order to
+ // determine the encoding to use.
+ long len = -1;
+ if (lobType == SQLData.BLOB)
+ {
+ len = blobValue_.length();
+ if(len > 80)
+ len = 80;
+ bytes = blobValue_.getBytes(position, (int)len);
+ } else
+ {
+ InputStream is = blobLocatorValue_.getBinaryStream();
+ bytes = new byte[80];
+ try
+ {
+ int bytesRead = is.read(bytes);
+ if (bytesRead == 0)
+ bytes = new byte[0];
+ } catch (Exception e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+ return null;
+ }finally
+ {
+ try{
+ is.close();
+ }catch(Exception e){
+ JDTrace.logException(this, "getString is.close()", e);
+ }
+ }
+ }
+ position += len-1;
+ if (bytes.length == 0)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+ while (i < bytes.length - 1
+ && ((bytes[i] == 0x20) || (bytes[i] == 0x40) || /* space */
+ (bytes[i] == 0x09) || (bytes[i] == 0x05) || /* tab */
+ (bytes[i] == 0x0d) || /* CR */
+ (bytes[i] == 0x0a) || bytes[i] == 0x15 /* LF */
+ || bytes[i] == 0))
+ {
+ if (bytes[i] == 0)
+ {
+ i++;
+ if ((bytes[i] == 0x20) || /* space */
+ (bytes[i] == 0x09) || /* table */
+ (bytes[i] == 0x0d) || /* CR */
+ (bytes[i] == 0x0a)) /* LF */
+ {
+ i++;
+ } else
+ {
+ i--;
+ nonWhiteSpaceByte = 0;
+ break;
+ }
+ } else
+ {
+ // If LE encoding..
+ if (bytes[i + 1] == 0)
+ {
+ i++;
+ }
+ i++;
+ }
+ }
+ if (i < (bytes.length - 1))
+ nonWhiteSpaceByte = bytes[i];
+ } /* while looking for nonspace byte */
+ /* We need to look at the next byte */
+ byte nextByte;
+ i++;
+ nextByte = bytes[i];
+
+ // Determine what the encoding is
+ if (nonWhiteSpaceByte == 0x3c)
+ {
+ if (nextByte == 0x00)
+ {
+ encoding = "UTF-16LE";
+ } else
+ {
+ encoding = "UTF-8";
+ }
+ } else if (nonWhiteSpaceByte == 0x00)
+ {
+ if (nextByte == 0x3c)
+ {
+ encoding = "UTF-16BE";
+ } else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+ } else if (nonWhiteSpaceByte == 0x4C /* < */)
+ {
+ //
+ // Determine the internal encoding. If it cannot be
+ // determined then use CCSID 37
+
+ encoding = getInternalEncodingFromEbcdic(bytes);
+ if (encoding == null)
+ {
+ encoding = "IBM-37";
+ }
+
+ } else
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ } // checking first byte
+ } // determine encoding
+ // At this point the encoding is set and we can obtain the
+ // string
+ InputStream stream = null;
+ BufferedReader reader = null;
+ StringBuffer sb = new StringBuffer();
+ try
+ {
+ if (lobType == SQLData.BLOB)
+ {
+ stream = blobValue_.getBinaryStream();
+ } else
+ {
+ stream = blobLocatorValue_.getBinaryStream();
+ }
+ while (byteOrderMarkSize > 0)
+ {
+ try
+ {
+ stream.read();
+ } catch ( IOException ioex)
+ {
+ // shouldn't ever happen since we've already looked at
+ // this.
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+ byteOrderMarkSize--;
+ }
+
+ try
+ {
+ reader = new BufferedReader(new InputStreamReader(stream,
+ encoding));
+ } catch (UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+ return null;
+ }
+
+
+ String line;
+ try
+ {
+ line = reader.readLine();
+ if (line != null)
+ {
+ sb.append(line);
+ }
+ line = reader.readLine();
+ while (line != null)
+ {
+ sb.append("\n");
+ sb.append(line);
+ line = reader.readLine();
+ }
+ } catch (IOException e)
+ {
+ throw JDError.throwSQLException(this, JDError.EXC_DATA_TYPE_MISMATCH);
+
+ }
+ } catch (Exception e)
+ {
+ throw JDError.throwSQLException(this, JDError.EXC_INTERNAL);
+
+ }finally
+ {
+ try{
+ if (stream != null) stream.close();
+ }catch(Exception e){
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logException(this, "stream.close() exception", e);
+ }
+ }
+ try{
+ if (reader != null) reader.close();
+ }catch(Exception e){
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logException(this, "reader.close() exception", e);
+ }
+ }
+ }
+ s = sb.toString();
+
+ break; // end of BLOB case
+/* ifdef JDBC40 */
+ case DOM_DOCUMENT:
+
+ DOMImplementation implementation = domDocument_.getImplementation();
+
+ DOMImplementationLS domImplementationLS = (DOMImplementationLS) implementation
+ .getFeature("LS", "3.0");
+ LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
+ s = lsSerializer.writeToString(domDocument_);
+
+ break;
+/* endif */
+
+ case 0:
+ //freed already
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ return null;
+ default:
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, "Invalid value: "+ lobType);
+ return null;
+ }
+ }
+ if(isXML_)//@xmltrim
+ return JDUtilities.stripXMLDeclaration(s); //@xmltrim
+ else
+ return s;
+ }
+
+
+ /**
+ Retrieves the internal encoding specified in the bytes that represent the beginning of an
+ XML document. If no internal encoding is present, then null is returned.
+ **/
+ private String getInternalEncodingFromEbcdic(byte[] bytes)
+ {
+ /* EBCDIC encoding for CCSID 37 and CCSID 290 for "encoding=" */
+ final byte[][] encodingPattern =
+ {
+ { (byte) 0x85, (byte) 0x95, (byte) 0x83, (byte) 0x96,
+ (byte) 0x84, (byte) 0x89, (byte) 0x95, (byte) 0x87 },
+ { (byte) 0x66, (byte) 0x76, (byte) 0x64, (byte) 0x77,
+ (byte) 0x65, (byte) 0x71, (byte) 0x76, (byte) 0x68 } };
+ String[] encodingName = { "IBM-37", "IBM-930" }; //@ibm-290 not supported
+
+ String encoding = null;
+ int i = 0;
+ int length = bytes.length;
+ while (bytes[i] != 0x4c && i < length)
+ {
+ i++;
+ }
+ i++; //one more
+ int currentPattern = -1;
+ int patternPosition = 0;
+ while (encoding == null && i < length && bytes[i] != 0x6e )
+ {
+ if (currentPattern < 0)
+ {
+ for (int j = 0; j < encodingPattern.length
+ && currentPattern < 0; j++)
+ {
+ if (bytes[i] == encodingPattern[j][0])
+ {
+ currentPattern = j;
+ patternPosition = 1;
+ }
+ }
+ } else
+ {
+ if (patternPosition == encodingPattern[currentPattern].length)
+ {
+ // Pick the encoding for the string to obtain the pattern
+ // from withing the string
+ encoding = encodingName[currentPattern];
+ // skip space
+
+ while (bytes[i] == 0x40 && i < length)
+ i++;
+ // make sure = is found. = is invariant at 0x7e
+ if (bytes[i] == 0x7e && i < length)
+ {
+ i++;
+ // Skip space
+ while (bytes[i] == 0x40 && i < length)
+ {
+ i++;
+ }
+ // Make sure " is found. " is invariant at 0x7f except
+ // for
+ // code pages 905 and 1026 (turkey) where it is found at
+ // 0xfc
+ if ((bytes[i] == 0x7f || ((0xff & bytes[i]) == 0xfc))
+ && (i < length))
+ {
+ i++;
+ // Find the ending quote
+ int endingQuote = i;
+ while (bytes[endingQuote] != 0x7f
+ && (( 0xFF & bytes[endingQuote]) != 0xfc)
+ && endingQuote < length)
+ {
+ endingQuote++;
+ }
+ if (endingQuote < length)
+ {
+ // Create a string from the bytes and return the
+ // encoding
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ bytes, i, endingQuote - i);
+
+ BufferedReader reader = null;
+ try
+ {
+ reader = new BufferedReader(
+ new InputStreamReader(
+ byteArrayInputStream,
+ encodingName[currentPattern]));
+ encoding = reader.readLine();
+ } catch (UnsupportedEncodingException e)
+ {
+ // Should never get here since the encoding should be valid
+ currentPattern = -1;
+ } catch (IOException e)
+ {
+ // Should never get here since we should get io exception on a byteArrayInputStream
+ currentPattern = -1;
+ }finally
+ {
+ try{
+ byteArrayInputStream.close();
+ }catch(Exception e){
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logException(this, "byteArayInputStream.close() exception", e);
+ }
+ }
+ try{
+ if (reader != null) reader.close();
+ }catch(Exception e){
+ if(JDTrace.isTraceOn())
+ {
+ JDTrace.logException(this, "reader.close() exception", e);
+ }
+
+ }
+ }
+
+ } else
+ {
+ currentPattern = -1;
+ }
+ } else
+ {
+ currentPattern = -1;
+ }
+ } else
+ {
+ currentPattern = -1;
+ }
+
+ } else
+ {
+ if (bytes[i] == encodingPattern[currentPattern][patternPosition])
+ {
+ patternPosition++;
+ } else
+ {
+ currentPattern = -1;
+ }
+ }
+ }
+ i++;
+ }
+
+ return encoding;
+ }
+
+ /**
+ * Writes the given Java String to the XML value that this SQLXML
object designates.
+ * @param str the string to be written to the XML value that this SQLXML
designates
+ * @throws SQLException if there is an error accessing the XML value
+ */
+ public synchronized void setString(String str) throws SQLException
+ {
+ freeInternals();
+ if(lobType == LOB_FREED)
+ {
+ JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
+ }
+
+ clobValue_ = new AS400JDBCClob(str, str.length(), isXML_);
+
+ lobType = SQLData.CLOB;
+ }
+
+
+ /**
+ Package level helper method. Only valid on Clob-like data.
+ Writes a String to this XML, starting at position position in the XML.
+ The XML 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 XML where writes should start.
+ @param string The string that will be written to the XML.
+ @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
+ **/
+ synchronized int setString(long position, String string, int offset, int lengthOfWrite) throws SQLException
+ {
+ switch (lobType)
+ {
+ case SQLData.DBCLOB:
+ case SQLData.CLOB:
+ return clobValue_.setString(position, string, offset, lengthOfWrite);
+ case SQLData.DBCLOB_LOCATOR:
+ case SQLData.CLOB_LOCATOR:
+ return clobLocatorValue_.setString(position, string, offset, lengthOfWrite);
+ default:
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, "Invalid value: "+ lobType);
+ return 0;
+ }
+
+
+ }
+
+
+ /**
+ * Retrieves the XML value designated by this SQLXML instance as a stream.
+ * @return a stream containing the XML data.
+ * @throws SQLException if there is an error processing the XML value.
+ * An exception is thrown if the state is not readable.
+ */
+ public synchronized InputStream getBinaryStream() throws SQLException
+ {
+ InputStream is = null;
+ switch (lobType)
+ {
+ case SQLData.DBCLOB:
+ case SQLData.CLOB:
+ try
+ {
+ // Check for an internal encoding in the string. If there is
+ // one, we must use it
+ String clobString = new String(clobValue_.data_);
+ String internalEncoding = getInternalEncoding(clobString);
+ if (internalEncoding != null)
+ {
+ is = new ByteArrayInputStream(clobString.getBytes(internalEncoding));
+ } else
+ {
+ is = new ByteArrayInputStream(clobString.getBytes("UTF-8"));
+ }
+ } catch (UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_XML_PARSING_ERROR, e);
+ return null;
+ }
+ break;
+ case SQLData.DBCLOB_LOCATOR:
+ case SQLData.CLOB_LOCATOR:
+ //This will also be the case for XML column data
+ if(isXML_) //@xml6 if xml column and thus also a locator, then get bytes from bloblocator code
+ is = blobLocatorValue_.getBinaryStream(); //@xml6 (no trim of XML declaration because it is binary)
+ else
+ {
+
+ try
+ {
+ // Check for an internal encoding in the string. If there is
+ // one, we must use it
+ String clobString = clobLocatorValue_.getSubString((long)1, (int)clobLocatorValue_.length());
+ String internalEncoding = getInternalEncoding(clobString);
+ if (internalEncoding != null)
+ {
+ is = new ByteArrayInputStream(clobString.getBytes(internalEncoding));
+ } else
+ {
+ is = new ByteArrayInputStream(clobString.getBytes("UTF-8"));
+ }
+ } catch (UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_XML_PARSING_ERROR, e);
+ return null;
+ }
+ }
+ break;
+ case SQLData.BLOB:
+ //
+ // In this case, we rely on the binary stream to identify its own encoding
+ // It appears the that binary encoding will be used the most.. However,
+ // this is not useful from a DB perspective since it cannot be searched.
+ //
+ is = blobValue_.getBinaryStream();
+
+ break;
+ case SQLData.BLOB_LOCATOR:
+ //
+ // In this case, we rely on the binary stream to identify its own encoding
+ // It appears the that binary encoding will be used the most.. However,
+ // this is not useful from a DB perspective since it cannot be searched.
+ //
+ is = blobLocatorValue_.getBinaryStream();
+
+ break;
+ // Obtain a stream from a dom document by first converting it to
+ // a String and then getting the UTF-8 representation
+ case DOM_DOCUMENT:
+ try
+ {
+ String string = this.getString();
+ is = new ByteArrayInputStream(string.getBytes("UTF-8"));
+
+ } catch (UnsupportedEncodingException e)
+ {
+ JDError.throwSQLException(this, JDError.EXC_XML_PARSING_ERROR, e);
+ return null;
+ }
+
+ break;
+ default:
+ {
+ JDError.throwSQLException(this, JDError.EXC_INTERNAL, "Invalid value: "+ lobType);
+ return null;
+ }
+ }
+ return is;
+ }
+
+
+
+ /**
+ * Returns a Source for reading the XML value designated by this SQLXML instance.
+ * Sources are used as inputs to XML parsers and XSLT transformers.
+ * @param sourceClass The class of the source, or null.
+ * If the class is null, a vendor specific Source implementation will be returned.
+ * The following classes are supported at a minimum:
+ *
+ * javax.xml.transform.dom.DOMSource - returns a DOMSource
+ * javax.xml.transform.sax.SAXSource - returns a SAXSource
+ * javax.xml.transform.stax.StAXSource - returns a StAXSource
+ * javax.xml.transform.stream.StreamSource - returns a StreamSource
+ *
+ * @return a Source for reading the XML value.
+ * @throws SQLException if there is an error processing the XML value
+ * or if this feature is not supported.
+ * The getCause() method of the exception may provide a more detailed exception, for example,
+ * if an XML parser exception occurs.
+ * An exception is thrown if the state is not readable.
+ */
+/* ifdef JDBC40 */
+ public synchronized
+ * javax.xml.transform.dom.DOMResult - returns a DOMResult
+ * javax.xml.transform.sax.SAXResult - returns a SAXResult
+ * javax.xml.transform.stax.StAXResult - returns a StAXResult
+ * javax.xml.transform.stream.StreamResult - returns a StreamResult
+ *
+ * @return Returns a Result for setting the XML value.
+ * @throws SQLException if there is an error processing the XML value
+ * or if this feature is not supported.
+ * The getCause() method of the exception may provide a more detailed exception, for example,
+ * if an XML parser exception occurs.
+ * An exception is thrown if the state is not writable.
+ * @exception If there is an error
+ */
+/* ifdef JDBC40 */
+ public synchronized 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
+ {
+ freeInternals();
+ lobType = LOB_FREED;
+ }
+
+
+ /**
+ * Free the internal representation used by the SQLXML.
+ * Call before setting a new type of internal representation
+ */
+ private void freeInternals() throws SQLException
+ {
+ if (blobValue_ != null)
+ {
+ blobValue_.free();
+ blobValue_ = null;
+ }
+ if (blobLocatorValue_ != null)
+ {
+ //blobLocatorValue_.free(); //@olddesc
+ blobLocatorValue_ = null;
+ }
+
+ if (clobValue_ != null)
+ {
+/* ifdef JDBC40 */
+ clobValue_.free();
+/* endif */
+ clobValue_ = null;
+ }
+
+ if (clobLocatorValue_ != null)
+ {
+ //clobLocatorValue_.free();//@olddesc
+ clobLocatorValue_ = null;
+ }
+
+ if (domDocument_ != null)
+ {
+ domDocument_ = null;
+ }
+ }
+ /**
+ * Retrieves the internal encoding specified in the string that represents
+ * an XML document. If no internal encoding is present, then null is
+ * returned.
+ */
+ private String getInternalEncoding(String xml)
+ {
+ String encoding = null;
+ // find the first <
+ int start = xml.indexOf("<");
+ if (start >= 0)
+ {
+ // find the ending >
+ int end = xml.indexOf(">", start);
+ if (end >= 0)
+ {
+ String piece = xml.substring(start, end + 1);
+ int encodingIndex = piece.indexOf("encoding=");
+ if (encodingIndex > 0)
+ {
+ int firstQuote = piece.indexOf("\"", encodingIndex);
+ if (firstQuote > 0)
+ {
+ int lastQuote = piece.indexOf("\"", firstQuote + 1);
+ if (lastQuote > 0)
+ {
+ return piece.substring(firstQuote + 1, lastQuote);
+ }
+ }
+ }
+ }
+ }
+ return encoding;
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/AS400JDBCSQLXMLLocator.java b/jdbc40/com/ibm/as400/access/AS400JDBCSQLXMLLocator.java
new file mode 100644
index 000000000..5de01bbf5
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AS400JDBCSQLXMLLocator.java
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AS400JDBCSQLXMLLocator.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) 2006-2009 International Business Machines Corporation and
+// others. All rights reserved.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+package com.ibm.as400.access;
+
+/* ifdef JDBC40 */
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXSource;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+/* endif */
+
+//import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
+
+
+//@PDA jdbc40 new class
+//@xml2 whole class is redesigned after that of The Native Driver
+/**
+
+
+ Full functionality of #1 and #2 requires OS/400 v5r2
+ or IBM i. If connecting to OS/400 V5R1 or earlier,
+ the value specified on these two methods will be ignored and the default holdability
+ will be the value of #3.
+
+ @exception SQLException If the statement is not open.
+
+ @since Modification 5
+ **/
+ public int getResultSetHoldability ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ {
+ checkOpen ();
+
+ //if we can get info from resultSet (post 540), that will be more accurate, since it can be from stored-proc cursor
+ if((resultSet_ != null) && (!resultSet_.isClosed())) //@cur //@cur2
+ return resultSet_.getHoldability(); //@cur
+
+ //@F4 If resultSetHoldability_ was set by the user, then return it. Otherwise,
+ //@F4 return the connection's holdability.
+ if((resultSetHoldability_ == AS400JDBCResultSet.HOLD_CURSORS_OVER_COMMIT) || //@F4A
+ (resultSetHoldability_ == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT)) //@F4A
+ {
+ //@F4A
+ return resultSetHoldability_; //@F4A
+ } //@F4A
+ return connection_.getHoldability();
+ }
+ }
+
+
+
+
+ // JDBC 2.0
+ /**
+ Returns the result set type to be used for this statement.
+
+ @return The result set type.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getResultSetType ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return resultSetType_;
+ }
+ }
+
+
+
+ /**
+ Returns the current update count.
+
+ @return The update count, or -1 if a result set was
+ returned or there are no more result sets.
+
+ @exception SQLException If the statement is not open.
+ **/
+ public int getUpdateCount ()
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ checkOpen ();
+ return(resultSet_ != null) ? -1 : updateCount_;
+ }
+ }
+
+
+
+ /**
+ Returns the first warning reported for the statement.
+ 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_;
+ }
+
+
+ //@KBL
+ /*
+ Sets whether or not the statement has been partially closed and if the remaining resources
+ should be freed when a transaction boundary is reached.
+ A statement may become partially closed if the user specified to keep statements associated with
+ locators open until a transaction boundary by setting the "hold statements" connection property to true.
+ */
+ void setHoldStatement(boolean hold){
+ holdStatement_ = hold;
+ }
+
+ //@KBL
+ /*
+ Returns whether or not the statement has been partially closed.
+ A statement may become partially closed if the user specified to keep statements associated with
+ locators open until a transaction boundary by setting the "hold statements" connection property to true.
+ */
+ boolean isHoldStatement()
+ {
+ return holdStatement_;
+ }
+
+ //@KBL
+ /*
+ Sets whether or not this statement object has been used to access a locator.
+ */
+ void setAssociatedWithLocators(boolean hasLocator){
+ associatedWithLocators_ = hasLocator;
+ }
+
+ //@KBL
+ /*
+ Returns whether or not this statement object has been used to access a locator.
+ */
+ boolean isAssociatedWithLocators(){
+ return associatedWithLocators_;
+ }
+
+ /**
+ Indicates if the statement is closed.
+
+ @return true if the statement is closed;
+ false otherwise.
+ **/
+ public boolean isClosed () throws SQLException //@PDC jdbc40
+ {
+ return closed_;
+ }
+
+
+
+ //@G4A
+ /**
+ Creates a result set to be returned from getGeneratedKeys().
+
+ Make an empty result set if return code is < 0 because the information
+ will not be waiting for us in the SQLCA.
+ **/
+ private void makeGeneratedKeyResultSet(int returnCode, DBReplySQLCA sqlca)
+ throws SQLException
+ {
+ //@F6A Make sure we close the generated key result set. We don't have to
+ //@F6A check to see if the user closed it already because close() does
+ //@F6A that for us already.
+ if(generatedKeys_ != null) //@F6A
+ {
+ //@F6A
+ generatedKeys_.close(); //@F6A
+ } //@F6A
+ //Code checks we are running to a v5r2 or later system before calling this method
+ BigDecimal generatedKey = null; //@F6C
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "returnCode is: " + returnCode);
+
+ if(returnCode < 0)
+ {
+ // If SQLCode (returnCode) from system is not 0, then don't go look
+ // for auto-generated key because it will not be there. Instead,
+ // make empty result set.
+ //@F6D generatedKey = "";
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "return code was not 0, generated key is null");
+ }
+ else
+ {
+ // As of right now, we will only be returned the last auto-generated key.
+ // Even though it is wasteful to return a ResultSet with only one element,
+ // that's what the spec. says we have to do.
+
+ // Consider going to system in the future to fill in the field name.
+ // Right now, it doesn't seem like a cost-effective trip.
+
+ // If there is no error, the errmc is instead filled with the auto-generated
+ // key for us.
+ generatedKey = sqlca.getGeneratedKey(); //@P0C @F6C Deleted converter
+ if(JDTrace.isTraceOn())
+ JDTrace.logInformation (this, "generated key from system is: " + generatedKey);
+ // generatedKey will be null if the database did not return to us a
+ // proper generatedKey
+ }
+ String[] fieldNames = {""};
+ SQLData[] sqlData = { new SQLDecimal (30, 0, settings_, connection_.getVRM(), connection_.getProperties())}; //@F6C // @M0C - changed SQLDecimal ctor signature
+ int[] fieldNullables = {AS400JDBCDatabaseMetaData.columnNoNulls};
+ JDSimpleRow formatRow = new JDSimpleRow (fieldNames, sqlData, fieldNullables);
+ boolean[][] nulls = {{false}};
+ boolean[][] dataMappingErrors = {{false}};
+ JDRowCache rowCache = null;
+ if(generatedKey == null)
+ {
+ rowCache = new JDSimpleRowCache(formatRow);
+ }
+ else
+ {
+ Object[][] data = {{generatedKey}};
+ rowCache = new JDSimpleRowCache (formatRow, data, nulls, dataMappingErrors);
+ }
+ // Construct with row cache, no catalog, and no cursor name
+ generatedKeys_ = new AS400JDBCResultSet (rowCache, "", "", connection_, null); //@in2
+ }
+
+
+
+ // @B3A
+ /**
+ Marks the cursor as closed.
+
+ @param isRollback True if we called this from rollback(), false if we called this from commit().
+ **/
+ void markCursorClosed(boolean isRollback) //@F4C
+ throws SQLException //@F2A
+ {
+ // @K94 - See if the user requested to hold cursors after a rollback
+ boolean rollbackCursorHold = connection_.getProperties().getBoolean(JDProperties.ROLLBACK_CURSOR_HOLD); //@K94
+ if(rollbackCursorHold) //@K94
+ isRollback = false; //@K94
+
+ // @F4 Added a check of statement level holdability because the user can specify the
+ // @F4 holdability of a specific statement (as a different value than the connection
+ // @F4 holdability) with JDBC 3.0 support. If this was called from Connection.rollback(),
+ // @F4 close all statements.
+ if((getResultSetHoldability() == AS400JDBCResultSet.CLOSE_CURSORS_AT_COMMIT //@F4A
+ || isRollback) //@F4A
+ && ((connection_.getVRM() <= JDUtilities.vrm610)
+ || ((connection_.getVRM() >= JDUtilities.vrm710) && cursor_.getCursorIsolationLevel() != 0))) //@isol only close if cursor's isolationlvl is not *none
+ {
+ //@F5D cursor_.setState(true);
+ //@F4 Instead of calling closeResultSet which does more work than we need to,
+ //@F4 just move the code here that we need to clean up our internal variables.
+ //@F4 Otherwise, we'd make an unnecessary flow to the system to tell it to
+ //@F4 close the cursor which it already has.
+ if(resultSet_ != null) //@F4A
+ {
+ //@F4A
+ if(! resultSet_.isClosed ()) //@F4A
+ resultSet_.close (); //@F4A
+ resultSet_ = null; //@F4A
+ } //@F4A
+ updateCount_ = -1; //@F4A
+ }
+ }
+
+
+
+
+ /**
+ Notifies the statement that its result set has been closed.
+
+ @exception SQLException If an error occurs.
+ **/
+ void notifyClose ()
+ throws SQLException
+ {
+ // The result set is close, so we can close the cursor.
+ if(! cursor_.isClosed ())
+ {
+ if(numberOfResults_ > 1) {
+ cursor_.close (JDCursor.REUSE_RESULT_SET);
+ } else {
+ // Only one result set.
+ cursor_.close (JDCursor.REUSE_YES);
+ }
+ }
+
+ // Close statement if closeOnCompletion_ and all results have been processed.
+ if (closeOnCompletion_ && numberOfResults_ <= 1) { // @D7A
+ this.close();
+ }
+ }
+
+
+
+ /**
+ Posts a warning for the statement.
+
+ @param sqlWarning The warning.
+ **/
+ void postWarning (SQLWarning sqlWarning)
+ {
+ if (JDTrace.isTraceOn ()) {
+ JDTrace.logInformation(this, "postWarning("+sqlWarning+")");
+ }
+
+ if(sqlWarning_ == null)
+ sqlWarning_ = sqlWarning;
+ else
+ sqlWarning_.setNextWarning (sqlWarning);
+ }
+
+
+
+ // @E9C
+ /**
+ Sets the SQL cursor name that will be used by the statement.
+ Cursor names must be unique within the connection.
+ The cursor name can only be set when no result set is open.
+
+ cursor hold
+ driver property.
+
+ The default is ResultSet.FETCH_FORWARD.
+
+ @exception SQLException If the statement is not open,
+ the result set type is
+ ResultSet.TYPE_FORWARD_ONLY,
+ and the input value is not
+ ResultSet.FETCH_FORWARD,
+ or the input value is not valid.
+ **/
+ public void setFetchDirection (int fetchDirection)
+ throws SQLException
+ {
+ synchronized(internalLock_)
+ { // @E6A
+ if(((fetchDirection != ResultSet.FETCH_FORWARD)
+ && (fetchDirection != ResultSet.FETCH_REVERSE)
+ && (fetchDirection != ResultSet.FETCH_UNKNOWN))
+ || ((resultSetType_ == ResultSet.TYPE_FORWARD_ONLY)
+ && (fetchDirection != ResultSet.FETCH_FORWARD)))
+ JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID);
+
+ checkOpen ();
+ fetchDirection_ = fetchDirection;
+
+ if(JDTrace.isTraceOn())
+ JDTrace.logProperty (this, "Fetch direction", fetchDirection_);
+ }
+ }
+
+
+
+ // JDBC 2.0
+ /**
+ Sets the number of rows to be fetched from the database when more
+ rows are needed. The number of rows specified only affects result
+ sets created using this statement. If the value specified is zero,
+ then the driver will choose an appropriate fetch size.
+
+ Statement
be pooled or not pooled. The value
+ * specified is a hint to the statement pool implementation indicating
+ * whether the applicaiton wants the statement to be pooled. It is up to
+ * the statement pool manager as to whether the hint is used.
+ * Statement
is poolable when it is created.
+ * Statement
has been closed
+ * Statement
has been closed
+ *
+
+@see AS400JDBCXAConnection
+@see AS400JDBCXAResource
+**/
+public class AS400JDBCXADataSource
+extends AS400JDBCDataSource
+implements XADataSource
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+
+ static final long serialVersionUID = 4L;
+
+/**
+Constructs a default AS400JDBCXADataSource object.
+**/
+ public AS400JDBCXADataSource()
+ {
+ super();
+ }
+
+
+
+/**
+Constructs an AS400JDBCXADataSource with the specified serverName.
+
+@param serverName The name of the IBM i system.
+**/
+ public AS400JDBCXADataSource(String serverName)
+ {
+ super(serverName);
+ }
+
+
+
+/**
+Constructs an AS400JDBCXADataSource with the specified signon information.
+
+@param serverName The name of the IBM i system.
+@param user The user id.
+@param password The password.
+**/
+ public AS400JDBCXADataSource(String serverName, String user, String password)
+ {
+ super(serverName, user, password);
+ }
+
+
+//@A1A
+/**
+Constructs an AS400JDBCXADataSource with the specified signon information
+to use for SSL communications with the IBM i system.
+
+@param serverName The name of the IBM i system.
+@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 AS400JDBCXADataSource(String serverName, String user, String password,
+ String keyRingName, String keyRingPassword)
+ {
+ super(serverName, user, password, keyRingName, keyRingPassword);
+ }
+
+
+// @F0A - added the following constructor to avoid some object construction
+/**
+* Constructs an AS400JDBCXADataSource from the specified Reference
+* @param reference to retrieve DataSource properties from
+**/
+ AS400JDBCXADataSource(Reference reference) {
+ super(reference);
+ }
+
+
+/**
+Returns an XA connection to IBM i.
+
+@return An XA connection.
+@exception SQLException If a database error occurs.
+**/
+ public XAConnection getXAConnection()
+ throws SQLException
+ {
+ AS400JDBCConnection connection = (AS400JDBCConnection)getConnection();
+ return new AS400JDBCXAConnection(connection);
+ }
+
+
+
+/**
+Returns an XA connection to IBM i.
+
+@param user The userid for the connection.
+@param password The password for the connection.
+@return An XA connection.
+@exception SQLException If a database error occurs.
+**/
+ public XAConnection getXAConnection(String user, String password)
+ throws SQLException
+ {
+ AS400JDBCConnection connection = (AS400JDBCConnection)getConnection(user, password);
+ return new AS400JDBCXAConnection(connection);
+ }
+
+
+
+/**
+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;
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/AbstractProxyImpl.java b/jdbc40/com/ibm/as400/access/AbstractProxyImpl.java
new file mode 100644
index 000000000..8cd1e95fd
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/AbstractProxyImpl.java
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: AbstractProxyImpl.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.lang.reflect.InvocationTargetException;
+
+// The AbstractProxyImpl class provides a default implementation for the ProxyImpl and ProxyFactoryImpl interfaces.
+abstract class AbstractProxyImpl
+/* ifdef JDBC40 */
+extends ToolboxWrapper
+/* endif */
+implements ProxyImpl, ProxyFactoryImpl
+{
+ static final String copyright = "Copyright (C) 1997-2010 International Business Machines Corporation and others.";
+
+ // Private data.
+ private String className_;
+ protected ProxyClientConnection connection_;
+ protected long pxId_;
+
+ // Called for ProxyFactoryImpl objects:
+ protected AbstractProxyImpl()
+ {
+ }
+
+ // Called for ProxyImpl objects:
+ protected AbstractProxyImpl(String className)
+ {
+ className_ = className;
+ }
+
+ // From the ProxyImpl interface:
+ public void construct(ProxyClientConnection connection)
+ {
+ connection_ = connection;
+ try
+ {
+ pxId_ = connection_.callConstructor(className_);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw ProxyClientConnection.rethrow(e);
+ }
+ }
+
+ // Cleans up the object.
+ protected void finalize() throws Throwable
+ {
+ connection_.callFinalize(pxId_);
+ super.finalize();
+ }
+
+ // From the ProxyImpl interface:
+ public long getPxId()
+ {
+ return pxId_;
+ }
+
+ // From the AbstractProxyImpl interface:
+ public void initialize(long pxId, ProxyClientConnection connection)
+ {
+ pxId_ = pxId;
+ connection_ = connection;
+ }
+}
diff --git a/jdbc40/com/ibm/as400/access/JDBlobProxy.java b/jdbc40/com/ibm/as400/access/JDBlobProxy.java
new file mode 100644
index 000000000..90af64c5d
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDBlobProxy.java
@@ -0,0 +1,206 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDBlobProxy.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.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Blob;
+import java.sql.SQLException;
+
+
+
+// JDBC 2.0
+/**
+The JDBlobProxy class provides access to binary large
+objects. The data is valid only within the current
+transaction.
+**/
+class JDBlobProxy
+extends AbstractProxyImpl
+implements Blob
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+ // Copied from JDError:
+ static final String EXC_FUNCTION_NOT_SUPPORTED = "IM001";
+
+
+ public InputStream getBinaryStream ()
+ throws SQLException
+ {
+ try {
+ JDInputStreamProxy newStream = new JDInputStreamProxy ();
+ return (JDInputStreamProxy) connection_.callFactoryMethod (
+ pxId_, "getBinaryStream", newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public byte[] getBytes (long start, int length)
+ throws SQLException
+ {
+ try {
+ return (byte[]) connection_.callMethod (pxId_, "getBytes",
+ new Class[] { Long.TYPE, Integer.TYPE },
+ new Object[] { new Long (start),
+ new Integer (length) })
+ .getReturnValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public long length ()
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "length")
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public long position (byte[] pattern, long start)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "position",
+ new Class[] { byte[].class, Long.TYPE },
+ new Object[] { pattern, new Long (start) })
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public long position (Blob pattern, long start)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "position",
+ new Class[] { Blob.class, Long.TYPE },
+ new Object[] { pattern, new Long (start) })
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 3.0
+ public OutputStream setBinaryStream (long pos)
+ throws SQLException
+ {
+ // Avoid dragging in JDError
+ //@K1D throw new SQLException (
+ //@K1D AS400JDBCDriver.getResource("JD" + EXC_FUNCTION_NOT_SUPPORTED),
+ //@K1D EXC_FUNCTION_NOT_SUPPORTED, -99999);
+ try //@K1A
+ {
+ JDOutputStreamProxy newStream = new JDOutputStreamProxy ();
+ return (JDOutputStreamProxy) connection_.callFactoryMethod (pxId_, "setBinaryStream",
+ new Class[] { Long.TYPE},
+ new Object[] { new Long(pos)},
+ newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 3.0
+ public int setBytes (long pos, byte[] bytes)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "setBytes",
+ new Class[] { Long.TYPE, byte[].class},
+ new Object[] { new Long(pos), bytes})
+ .getReturnValueInt ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 3.0
+ public int setBytes (long pos, byte[] bytes, int offset, int len)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "setBytes",
+ new Class[] { Long.TYPE, byte[].class, Integer.TYPE, Integer.TYPE},
+ new Object[] { new Long(pos), bytes, new Integer(offset), new Integer(len)})
+ .getReturnValueInt ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 3.0
+ public void truncate (long len)
+ throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, "truncate",
+ new Class[] { Long.TYPE},
+ new Object[] { new Long(len)});
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ //@PDA jdbc40
+ public synchronized void free() throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, "free");
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public synchronized InputStream getBinaryStream(long pos, long length) throws SQLException
+ {
+ try {
+ JDInputStreamProxy newStream = new JDInputStreamProxy ();
+ return (JDInputStreamProxy) connection_.callFactoryMethod (
+ pxId_, "getBinaryStream",
+ new Class[] { Long.TYPE, Long.TYPE},
+ new Object[] { new Long(pos), new Long(length)},
+ newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDCallableStatementProxy.java b/jdbc40/com/ibm/as400/access/JDCallableStatementProxy.java
new file mode 100644
index 000000000..545775293
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDCallableStatementProxy.java
@@ -0,0 +1,1825 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDCallableStatementProxy.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.InputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Date;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+import java.sql.Ref;
+/* ifdef JDBC40 */
+import java.sql.RowId;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLXML;
+/* endif */
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.Map;
+import java.util.Vector;
+
+
+
+class JDCallableStatementProxy
+extends JDPreparedStatementProxy
+implements CallableStatement
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+ private Vector registeredTypes_ = new Vector ();
+ // Note: We will only use elements starting at index 1.
+ // The Vector element at index 0 will simply be a place-holder.
+ // This way we can match parameter indexes directory to element indexes.
+
+ // Copied from JDError:
+ static final String EXC_FUNCTION_NOT_SUPPORTED = "IM001";
+
+ private final static String NOT_SERIALIZABLE = "Parameter is not serializable.";
+
+ public JDCallableStatementProxy (JDConnectionProxy jdConnection)
+ {
+ super (jdConnection);
+ }
+
+
+ // Call a method, and return a 'raw' ProxyReturnValue.
+ private ProxyReturnValue callMethodRtnRaw (String methodName, int argValue)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (argValue) });
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ // Added for JDBC 3.0 support
+ // Call a method, and return a 'raw' ProxyReturnValue.
+ private ProxyReturnValue callMethodRtnRaw (String methodName, String argValue)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ new Class[] { String.class},
+ new Object[] { argValue});
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ // Added for JDBC 3.0 support
+ private int findParameterIndex(String parameterName)
+ throws SQLException
+ {
+ try
+ {
+ return((Integer)connection_.callMethod (pxId_, "findParameterIndex",
+ new Class[] { String.class},
+ new Object[] { parameterName})
+ .getReturnValue())
+ .intValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+
+// JDBC 2.0
+ public Array getArray (int parameterIndex)
+ throws SQLException
+ {
+ return (Array) callMethodRtnRaw ("getArray", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Array getArray (String parameterName)
+ throws SQLException
+ {
+ return(Array) callMethodRtnRaw ("getArray", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public BigDecimal getBigDecimal (int parameterIndex)
+ throws SQLException
+ {
+ return (BigDecimal) callMethodRtnRaw ("getBigDecimal", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public BigDecimal getBigDecimal (String parameterName)
+ throws SQLException
+ {
+ return(BigDecimal) callMethodRtnRaw ("getBigDecimal", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+/**
+@exception SQLException If a SQL error occurs.
+@deprecated Use getBigDecimal(int) instead.
+@see #getBigDecimal(int)
+**/
+ public BigDecimal getBigDecimal (int parameterIndex, int scale)
+ throws SQLException
+ {
+ return (BigDecimal) callMethodRtnRaw ("getBigDecimal",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (scale) })
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public Blob getBlob (int parameterIndex)
+ throws SQLException
+ {
+ try {
+ JDBlobProxy newBlob = new JDBlobProxy ();
+ return (JDBlobProxy) connection_.callFactoryMethod (
+ pxId_,
+ "getBlob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(parameterIndex) },
+ newBlob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 3.0
+ public Blob getBlob (String parameterName)
+ throws SQLException
+ {
+ try {
+ JDBlobProxy newBlob = new JDBlobProxy ();
+ return(JDBlobProxy) connection_.callFactoryMethod (
+ pxId_,
+ "getBlob",
+ new Class[] { String.class},
+ new Object[] { parameterName},
+ newBlob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+
+ public boolean getBoolean (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getBoolean", parameterIndex)
+ .getReturnValueBoolean ();
+ }
+
+
+
+// JDBC 3.0
+ public boolean getBoolean (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getBoolean", parameterName)
+ .getReturnValueBoolean ();
+ }
+
+
+
+ public byte getByte (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getByte", parameterIndex)
+ .getReturnValueByte ();
+ }
+
+
+
+//JDBC 3.0
+ public byte getByte (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getByte", parameterName)
+ .getReturnValueByte ();
+ }
+
+
+
+ public byte[] getBytes (int parameterIndex)
+ throws SQLException
+ {
+ return (byte[]) callMethodRtnRaw ("getBytes", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public byte[] getBytes (String parameterName)
+ throws SQLException
+ {
+ return(byte[]) callMethodRtnRaw ("getBytes", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public Clob getClob (int parameterIndex)
+ throws SQLException
+ {
+ try {
+ JDClobProxy newClob = new JDClobProxy ();
+ return (JDClobProxy) connection_.callFactoryMethod (
+ pxId_,
+ "getClob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(parameterIndex) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+// JDBC 3.0
+ public Clob getClob (String parameterName)
+ throws SQLException
+ {
+ try {
+ JDClobProxy newClob = new JDClobProxy ();
+ return(JDClobProxy) connection_.callFactoryMethod (
+ pxId_,
+ "getClob",
+ new Class[] { String.class},
+ new Object[] { parameterName},
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+
+ public Date getDate (int parameterIndex)
+ throws SQLException
+ {
+ return (Date) callMethodRtnRaw ("getDate", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Date getDate (String parameterName)
+ throws SQLException
+ {
+ return(Date) callMethodRtnRaw ("getDate", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public Date getDate (int parameterIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Date) callMethodRtnRaw ("getDate",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ calendar })
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Date getDate (String parameterName, Calendar calendar)
+ throws SQLException
+ {
+ return(Date) callMethodRtnRaw ("getDate",
+ new Class[] { String.class, Calendar.class},
+ new Object[] { parameterName,
+ calendar})
+ .getReturnValue ();
+ }
+
+
+
+ public double getDouble (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getDouble", parameterIndex)
+ .getReturnValueDouble ();
+ }
+
+
+
+// JDBC 3.0
+ public double getDouble (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getDouble", parameterName)
+ .getReturnValueDouble ();
+ }
+
+
+
+ public float getFloat (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getFloat", parameterIndex)
+ .getReturnValueFloat ();
+ }
+
+
+
+// JDBC 3.0
+ public float getFloat (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getFloat", parameterName)
+ .getReturnValueFloat ();
+ }
+
+
+
+ public int getInt (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getInt", parameterIndex)
+ .getReturnValueInt ();
+ }
+
+
+
+// JDBC 3.0
+ public int getInt (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getInt", parameterName)
+ .getReturnValueInt ();
+ }
+
+
+
+ public long getLong (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getLong", parameterIndex)
+ .getReturnValueLong ();
+ }
+
+
+
+// JDBC 3.0
+ public long getLong (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getLong", parameterName)
+ .getReturnValueLong ();
+ }
+
+
+
+ public Object getObject (int parameterIndex)
+ throws SQLException
+ {
+ try
+ {
+ if (parameterIndex > 0 &&
+ parameterIndex < registeredTypes_.size() )
+ {
+ Integer typeInt = (Integer)registeredTypes_.elementAt(parameterIndex);
+ if (typeInt != null)
+ {
+ int type = typeInt.intValue();
+ ProxyFactoryImpl proxyObject = null;
+ if (type == Types.BLOB) {
+ proxyObject = new JDBlobProxy ();
+ }
+ else if (type == Types.CLOB) {
+ proxyObject = new JDClobProxy ();
+ }
+ if (proxyObject != null) {
+ return connection_.callFactoryMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (parameterIndex) },
+ proxyObject);
+ }
+ }
+ }
+ return connection_.callMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (parameterIndex) })
+ .getReturnValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 2.0
+ public Object getObject (int parameterIndex, Map typeMap)
+ throws SQLException
+ {
+ try
+ {
+ if (parameterIndex > 0 &&
+ parameterIndex < registeredTypes_.size() )
+ {
+ Integer typeInt = (Integer)registeredTypes_.elementAt(parameterIndex);
+ if (typeInt != null)
+ {
+ int type = typeInt.intValue();
+ ProxyFactoryImpl proxyObject = null;
+ if (type == Types.BLOB) {
+ proxyObject = new JDBlobProxy ();
+ }
+ else if (type == Types.CLOB) {
+ proxyObject = new JDClobProxy ();
+ }
+ if (proxyObject != null) {
+ return connection_.callFactoryMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE, Map.class },
+ new Object[] { new Integer (parameterIndex),
+ typeMap },
+ proxyObject);
+ }
+ }
+ }
+ return connection_.callMethod (pxId_, "getObject",
+ new Class[] { Integer.TYPE, Map.class },
+ new Object[] { new Integer (parameterIndex),
+ typeMap })
+ .getReturnValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+// JDBC 3.0
+ public Object getObject (String parameterName)
+ throws SQLException
+ {
+ return getObject (findParameterIndex(parameterName));
+ }
+
+
+
+// JDBC 3.0
+ public Object getObject (String parameterName, Map typeMap)
+ throws SQLException
+ {
+ return getObject(findParameterIndex(parameterName), typeMap);
+ }
+
+
+
+
+// JDBC 2.0
+ public Ref getRef (int parameterIndex)
+ throws SQLException
+ {
+ return (Ref) callMethodRtnRaw ("getRef", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Ref getRef (String parameterName)
+ throws SQLException
+ {
+ return(Ref) callMethodRtnRaw ("getRef", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+ public short getShort (int parameterIndex)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getShort", parameterIndex)
+ .getReturnValueShort ();
+ }
+
+
+// JDBC 3.0
+ public short getShort (String parameterName)
+ throws SQLException
+ {
+ return callMethodRtnRaw ("getShort", parameterName)
+ .getReturnValueShort ();
+ }
+
+
+
+ public String getString (int parameterIndex)
+ throws SQLException
+ {
+ return (String) callMethodRtnRaw ("getString", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public String getString (String parameterName)
+ throws SQLException
+ {
+ return(String) callMethodRtnRaw ("getString", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+ public Time getTime (int parameterIndex)
+ throws SQLException
+ {
+ return (Time) callMethodRtnRaw ("getTime", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Time getTime (String parameterName)
+ throws SQLException
+ {
+ return(Time) callMethodRtnRaw ("getTime", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public Time getTime (int parameterIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Time) callMethodRtnRaw ("getTime",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ calendar })
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Time getTime (String parameterName, Calendar calendar)
+ throws SQLException
+ {
+ return(Time) callMethodRtnRaw ("getTime",
+ new Class[] { String.class, Calendar.class},
+ new Object[] { parameterName,
+ calendar})
+ .getReturnValue ();
+ }
+
+
+
+ public Timestamp getTimestamp (int parameterIndex)
+ throws SQLException
+ {
+ return (Timestamp) callMethodRtnRaw ("getTimestamp", parameterIndex)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Timestamp getTimestamp (String parameterName)
+ throws SQLException
+ {
+ return(Timestamp) callMethodRtnRaw ("getTimestamp", parameterName)
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 2.0
+ public Timestamp getTimestamp (int parameterIndex, Calendar calendar)
+ throws SQLException
+ {
+ return (Timestamp) callMethodRtnRaw ("getTimestamp",
+ new Class[] { Integer.TYPE, Calendar.class },
+ new Object[] { new Integer (parameterIndex),
+ calendar })
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public Timestamp getTimestamp (String parameterName, Calendar calendar)
+ throws SQLException
+ {
+ return(Timestamp) callMethodRtnRaw ("getTimestamp",
+ new Class[] { String.class, Calendar.class},
+ new Object[] { parameterName,
+ calendar})
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public URL getURL (int parameterIndex)
+ throws SQLException
+ {
+ return(URL) callMethodRtnRaw ("getURL",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (parameterIndex)})
+ .getReturnValue ();
+ }
+
+
+
+// JDBC 3.0
+ public URL getURL (String parameterName)
+ throws SQLException
+ {
+ return(URL) callMethodRtnRaw ("getURL",
+ new Class[] { String.class},
+ new Object[] { parameterName})
+ .getReturnValue ();
+ }
+
+
+
+ private void registerLocally (int parameterIndex, int sqlType)
+ {
+ for (int i=registeredTypes_.size(); i<=parameterIndex; i++)
+ registeredTypes_.addElement (null);
+ registeredTypes_.setElementAt (new Integer(sqlType), parameterIndex);
+ }
+
+
+
+ public void registerOutParameter (int parameterIndex,
+ int sqlType,
+ int scale)
+ throws SQLException
+ {
+ callMethod ("registerOutParameter",
+ new Class[] { Integer.TYPE, Integer.TYPE,
+ Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (sqlType),
+ new Integer (scale) });
+
+ registerLocally (parameterIndex, sqlType); //@A1C
+ }
+
+
+ public void registerOutParameter (int parameterIndex, int sqlType)
+ throws SQLException
+ {
+ callMethod ("registerOutParameter",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (sqlType) });
+
+ registerLocally (parameterIndex, sqlType); //@A1C
+ }
+
+
+ public void registerOutParameter (int parameterIndex, int sqlType, String typeName)
+ throws SQLException
+ {
+
+ callMethod ("registerOutParameter",
+ new Class[] { Integer.TYPE, Integer.TYPE,
+ String.class },
+ new Object[] { new Integer (parameterIndex),
+ new Integer (sqlType),
+ new Integer (typeName) });
+
+ registerLocally (parameterIndex, sqlType); //@A1C
+ }
+
+
+
+// JDBC 3.0
+ public void registerOutParameter (String parameterName, int sqlType)
+ throws SQLException
+ {
+ registerOutParameter(findParameterIndex(parameterName), sqlType);
+ }
+
+
+
+// JDBC 3.0
+ public void registerOutParameter (String parameterName, int sqlType, int scale)
+ throws SQLException
+ {
+ registerOutParameter(findParameterIndex(parameterName), sqlType, scale);
+ }
+
+
+
+// JDBC 3.0
+ public void registerOutParameter (String parameterName, int sqlType, String typeName)
+ throws SQLException
+ {
+ registerOutParameter(findParameterIndex(parameterName), sqlType, typeName);
+ }
+
+
+
+// JDBC 3.0
+ public void setAsciiStream (String parameterName, InputStream parameterValue, int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (parameterValue == null ||
+ parameterValue instanceof Serializable)
+ iStream = parameterValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (parameterValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { String.class, InputStream.class,
+ Integer.TYPE},
+ new Object[] { parameterName,
+ iStream,
+ new Integer (length)});
+ }
+
+
+
+// JDBC 3.0
+ public void setBigDecimal (String parameterName, BigDecimal parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBigDecimal",
+ new Class[] { String.class, BigDecimal.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+
+// JDBC 3.0
+ public void setBinaryStream (String parameterName,
+ InputStream parameterValue,
+ int length)
+ throws SQLException
+ {
+ InputStream iStream;
+ if (parameterValue == null ||
+ parameterValue instanceof Serializable)
+ iStream = parameterValue;
+ else {
+ try {
+ iStream = new SerializableInputStream (parameterValue);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { String.class, InputStream.class,
+ Integer.TYPE},
+ new Object[] { parameterName,
+ iStream,
+ new Integer (length)});
+ }
+
+
+
+
+// JDBC 3.0
+ public void setBoolean (String parameterName, boolean parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBoolean",
+ new Class[] { String.class, Boolean.TYPE},
+ new Object[] { parameterName,
+ new Boolean(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setByte (String parameterName, byte parameterValue)
+ throws SQLException
+ {
+ callMethod ("setByte",
+ new Class[] { String.class, Byte.TYPE},
+ new Object[] { parameterName,
+ new Byte(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setBytes (String parameterName, byte[] parameterValue)
+ throws SQLException
+ {
+ callMethod ("setBytes",
+ new Class[] { String.class, byte[].class}, //@K1C Changed from Byte.class to byte[].class
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+//JDBC 3.0
+ public void setCharacterStream (String parameterName,
+ Reader parameterValue,
+ int length)
+ throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (parameterValue == null)
+ reader = null;
+ else
+ reader = new SerializableReader (parameterValue, Math.max(0,length));
+ callMethod ("setCharacterStream",
+ new Class[] { String.class, Reader.class,
+ Integer.TYPE},
+ new Object[] { parameterName,
+ reader,
+ new Integer (length)});
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+
+// JDBC 3.0
+ public void setDate (String parameterName, Date parameterValue)
+ throws SQLException
+ {
+ callMethod ("setDate",
+ new Class[] { String.class, Date.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+// JDBC 3.0
+ public void setDate (String parameterName, Date parameterValue, Calendar cal)
+ throws SQLException
+ {
+ callMethod ("setDate",
+ new Class[] { String.class, Date.class, Calendar.class},
+ new Object[] { parameterName,
+ parameterValue, cal});
+ }
+
+
+
+// JDBC 3.0
+ public void setDouble (String parameterName, double parameterValue)
+ throws SQLException
+ {
+ callMethod ("setDouble",
+ new Class[] { String.class, Double.TYPE},
+ new Object[] { parameterName,
+ new Double(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setFloat (String parameterName, float parameterValue)
+ throws SQLException
+ {
+ callMethod ("setFloat",
+ new Class[] { String.class, Float.TYPE},
+ new Object[] { parameterName,
+ new Float(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setInt (String parameterName, int parameterValue)
+ throws SQLException
+ {
+ callMethod ("setInt",
+ new Class[] { String.class, Integer.TYPE},
+ new Object[] { parameterName,
+ new Integer(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setLong (String parameterName, long parameterValue)
+ throws SQLException
+ {
+ callMethod ("setLong",
+ new Class[] { String.class, Long.TYPE},
+ new Object[] { parameterName,
+ new Long(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setNull (String parameterName, int sqlType)
+ throws SQLException
+ {
+ callMethod ("setNull",
+ new Class[] { String.class, Integer.TYPE},
+ new Object[] { parameterName,
+ new Integer(sqlType)});
+ }
+
+
+
+// JDBC 3.0
+ public void setNull (String parameterName, int sqlType, String typeName)
+ throws SQLException
+ {
+ callMethod ("setNull",
+ new Class[] { String.class, Integer.TYPE, String.class},
+ new Object[] { parameterName,
+ new Integer(sqlType), typeName});
+ }
+
+
+
+// JDBC 3.0
+ public void setObject (String parameterName, Object parameterValue)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { String.class, Object.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+// JDBC 3.0
+ public void setObject (String parameterName,
+ Object parameterValue,
+ int sqlType)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { String.class, Object.class,
+ Integer.TYPE},
+ new Object[] { parameterName,
+ parameterValue,
+ new Integer (sqlType)});
+ }
+
+
+
+// JDBC 3.0
+ public void setObject (String parameterName,
+ Object parameterValue,
+ int sqlType,
+ int scale)
+ throws SQLException
+ {
+ if (parameterValue != null &&
+ !(parameterValue instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setObject",
+ new Class[] { String.class, Object.class,
+ Integer.TYPE, Integer.TYPE},
+ new Object[] { parameterName,
+ parameterValue,
+ new Integer (sqlType),
+ new Integer (scale)});
+ }
+
+
+
+
+// JDBC 3.0
+ public void setShort (String parameterName, short parameterValue)
+ throws SQLException
+ {
+ callMethod ("setShort",
+ new Class[] { String.class, Short.TYPE},
+ new Object[] { parameterName,
+ new Short(parameterValue)});
+ }
+
+
+
+// JDBC 3.0
+ public void setString (String parameterName, String sqlType)
+ throws SQLException
+ {
+ callMethod ("setString",
+ new Class[] { String.class, String.class},
+ new Object[] { parameterName,
+ sqlType});
+ }
+
+
+
+// JDBC 3.0
+ public void setTime (String parameterName, Time parameterValue)
+ throws SQLException
+ {
+ callMethod ("setTime",
+ new Class[] { String.class, Time.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+// JDBC 3.0
+ public void setTime (String parameterName, Time parameterValue, Calendar cal)
+ throws SQLException
+ {
+ callMethod ("setTime",
+ new Class[] { String.class, Time.class, Calendar.class},
+ new Object[] { parameterName,
+ parameterValue, cal});
+ }
+
+
+
+// JDBC 3.0
+ public void setTimestamp (String parameterName, Timestamp parameterValue)
+ throws SQLException
+ {
+ callMethod ("setTimestamp",
+ new Class[] { String.class, Timestamp.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+// JDBC 3.0
+ public void setTimestamp (String parameterName, Timestamp parameterValue, Calendar cal)
+ throws SQLException
+ {
+ callMethod ("setTimestamp",
+ new Class[] { String.class, Timestamp.class, Calendar.class},
+ new Object[] { parameterName,
+ parameterValue, cal});
+ }
+
+
+
+// JDBC 3.0
+ public void setURL (String parameterName, URL parameterValue)
+ throws SQLException
+ {
+ callMethod ("setURL",
+ new Class[] { String.class, URL.class},
+ new Object[] { parameterName,
+ parameterValue});
+ }
+
+
+
+ public boolean wasNull ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("wasNull");
+ }
+
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.CallableStatement" };
+ }
+
+
+
+ //@PDA jdbc40
+ public Reader getCharacterStream(int parameterIndex) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getCharacterStream",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (parameterIndex) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public Reader getCharacterStream(String parameterName) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getCharacterStream",
+ new Class[] { String.class },
+ new Object[] { new Integer (parameterName) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public Reader getNCharacterStream(int parameterIndex) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getNCharacterStream",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (parameterIndex) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public Reader getNCharacterStream(String parameterName) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getNCharacterStream",
+ new Class[] { String.class },
+ new Object[] { new Integer (parameterName) },
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public NClob getNClob(int parameterIndex) throws SQLException
+ {
+ try {
+ JDNClobProxy newClob = new JDNClobProxy ();
+ return (JDNClobProxy) connection_.callFactoryMethod (pxId_,
+ "getNClob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(parameterIndex) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public NClob getNClob(String parameterName) throws SQLException
+ {
+ try {
+ JDNClobProxy newClob = new JDNClobProxy ();
+ return (JDNClobProxy) connection_.callFactoryMethod (pxId_,
+ "getNClob",
+ new Class[] { String.class },
+ new Object[] { new Integer(parameterName) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+/* endif */
+
+ //@PDA jdbc40
+ public String getNString(int parameterIndex) throws SQLException
+ {
+ return (String) callMethodRtnRaw ("getNString", parameterIndex).getReturnValue ();
+ }
+
+ //@PDA jdbc40
+ public String getNString(String parameterName) throws SQLException
+ {
+ return (String) callMethodRtnRaw ("getNString", parameterName).getReturnValue ();
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public RowId getRowId(int parameterIndex) throws SQLException
+ {
+ try {
+ JDRowIdProxy newRowId = new JDRowIdProxy ();
+ return (JDRowIdProxy) connection_.callFactoryMethod (pxId_,
+ "getRowId",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(parameterIndex) },
+ newRowId);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public RowId getRowId(String parameterName) throws SQLException
+ {
+ try {
+ JDRowIdProxy newRowId = new JDRowIdProxy ();
+ return (JDRowIdProxy) connection_.callFactoryMethod (pxId_,
+ "getRowId",
+ new Class[] { String.class },
+ new Object[] { new Integer(parameterName) },
+ newRowId);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+/* endif */
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public SQLXML getSQLXML(int parameterIndex) throws SQLException
+ {
+ try {
+ JDSQLXMLProxy newXML = new JDSQLXMLProxy ();
+ return (JDSQLXMLProxy) connection_.callFactoryMethod (pxId_,
+ "getSQLXML",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(parameterIndex) },
+ newXML);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ public SQLXML getSQLXML(String parameterName) throws SQLException
+ {
+ try {
+ JDSQLXMLProxy newXML = new JDSQLXMLProxy ();
+ return (JDSQLXMLProxy) connection_.callFactoryMethod (pxId_,
+ "getSQLXML",
+ new Class[] { String.class },
+ new Object[] { new Integer(parameterName) },
+ newXML);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+/* endif */
+ //@PDA jdbc40
+ public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { String.class, InputStream.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { String.class, InputStream.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setBlob(String parameterName, Blob x) throws SQLException
+ {
+ if (x != null &&
+ !(x instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setBlob",
+ new Class[] { String.class, Blob.class },
+ new Object[] { parameterName,
+ x });
+ }
+
+ //@PDA jdbc40
+ public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (inputStream == null ||
+ inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBlob",
+ new Class[] { String.class, InputStream.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialReader;
+ if (reader == null)
+ serialReader = null;
+ else
+ serialReader = new SerializableReader (reader, (int)Math.max(0,length));
+ callMethod ("setCharacterStream",
+ new Class[] { String.class, Reader.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ serialReader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void setClob(String parameterName, Clob x) throws SQLException
+ {
+ if (x != null &&
+ !(x instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setClob",
+ new Class[] { String.class, Clob.class },
+ new Object[] { parameterName,
+ x });
+ }
+
+ //@PDA jdbc40
+ public void setClob(String parameterName, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader, (int) Math.max(0,length));
+ callMethod ("setClob",
+ new Class[] { String.class, Reader.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ serialRreader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (value == null)
+ reader = null;
+ else
+ reader = new SerializableReader (value, (int) Math.max(0,length));
+ callMethod ("setNCharacterStream",
+ new Class[] { String.class, Reader.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ reader,
+ new Long(length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public void setNClob(String parameterName, NClob value) throws SQLException
+ {
+ if (value != null &&
+ !(value instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setNClob",
+ new Class[] { String.class, NClob.class },
+ new Object[] { parameterName,
+ value });
+ }
+
+/* endif */
+
+ //@PDA jdbc40
+ public void setNClob(String parameterName, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader, (int) Math.max(0,length));
+ callMethod ("setNClob",
+ new Class[] { String.class, Reader.class,
+ Long.TYPE },
+ new Object[] { parameterName,
+ serialRreader,
+ new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void setNString(String parameterName, String value) throws SQLException
+ {
+ callMethod ("setNString",
+ new Class[] { String.class, String.class },
+ new Object[] { parameterName, value });
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public void setRowId(String parameterName, RowId x) throws SQLException
+ {
+ callMethod ("setRowId",
+ new Class[] { String.class, RowId.class},
+ new Object[] { parameterName, x });
+ }
+
+ //@PDA jdbc40
+ public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException
+ {
+ if (xmlObject != null &&
+ !(xmlObject instanceof Serializable) ){
+ if (JDTrace.isTraceOn())
+ JDTrace.logInformation (this, NOT_SERIALIZABLE);
+ throw new SQLException ();
+ }
+
+ callMethod ("setSQLXML",
+ new Class[] { String.class, SQLXML.class },
+ new Object[] { parameterName,
+ xmlObject });
+ }
+
+/* endif */
+
+ public void setAsciiStream(String parameterName, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setAsciiStream",
+ new Class[] { String.class, InputStream.class },
+ new Object[] { parameterName,
+ iStream });
+ }
+
+
+ public void setBinaryStream(String parameterName, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null ||
+ x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBinaryStream",
+ new Class[] { String.class, InputStream.class },
+ new Object[] { parameterName,
+ iStream });
+ }
+
+
+ public void setBlob(String parameterName, InputStream inputStream) throws SQLException
+ {
+ InputStream iStream;
+ if (inputStream == null ||
+ inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("setBlob",
+ new Class[] { String.class, InputStream.class },
+ new Object[] { parameterName,
+ iStream });
+ }
+
+
+ public void setCharacterStream(String parameterName, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader);
+ callMethod ("setCharacterStream",
+ new Class[] { String.class, Reader.class },
+ new Object[] { parameterName,
+ serialRreader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ public void setClob(String parameterName, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader);
+ callMethod ("setClob",
+ new Class[] { String.class, Reader.class },
+ new Object[] { parameterName,
+ serialRreader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ public void setNCharacterStream(String parameterName, Reader value) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (value == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (value);
+ callMethod ("setNCharacterStream",
+ new Class[] { String.class, Reader.class },
+ new Object[] { parameterName,
+ serialRreader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ public void setNClob(String parameterName, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader serialRreader;
+ if (reader == null)
+ serialRreader = null;
+ else
+ serialRreader = new SerializableReader (reader);
+ callMethod ("setNClob",
+ new Class[] { String.class, Reader.class },
+ new Object[] { parameterName,
+ serialRreader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+/* ifdef JDBC40 */
+
+ // JDBC 4.1
+ public
+// Create an XA data source for making the connection.
+AS400JDBCXADataSource xaDataSource = new AS400JDBCXADataSource("myAS400");
+xaDataSource.setUser("myUser");
+xaDataSource.setPassword("myPasswd");
+
+// Get the XAConnection.
+XAConnection xaConnection = xaDataSource.getXAConnection();
+
DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver
+ * and the maximum length that may be specified for each property.
+ * SQLException
. If the driver
+ * generates a SQLException
, the value specified was not set on the
+ * connection.
+ *
+ *
+ * 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.
+ * 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.
+ *
+ *
+ * DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver.
+ *
+ *
+ *
+ *
+ * Properties
object that contains the name and current value of
+ * each of the client info properties supported by the driver.
+ * 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 (Clob) callMethodRtnObj("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
+ {
+ return (Blob) callMethodRtnObj("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
+ {
+ return (NClob) callMethodRtnObj("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
+ {
+ return (SQLXML) callMethodRtnObj("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
+ {
+ return (Array) callMethodRtnObj("createArrayOf",
+ new Class[] { String.class, Object[].class },
+ new Object[] { 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
+ {
+ return (Struct) callMethodRtnObj("createStruct",
+ new Class[] { String.class, Object[].class },
+ new Object[] { typeName, attributes });
+ }
+
+ //@pd2 add missing proxy method. This is needed for various testcases that use jobid.
+ /**
+ 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:
+
+
+
+
+
+ @return The server job identifier, or null if not known.
+ **/
+ public String getServerJobIdentifier() throws SQLException // @pd2
+ { // @pd2
+ return (String) callMethodRtnObj("getServerJobIdentifier"); // @pd2
+ } // @pd2
+
+/* ifdef JDBC40 */
+
+ // JDBC 4.1
+ public void abort(Executor executor) throws SQLException {
+ callMethod("abort",
+ new Class[] {Executor.class},
+ new Object[] {executor});
+ }
+
+ // JDBC 4.1
+ public void setNetworkTimeout(Executor executor, int milliseconds)
+ throws SQLException {
+ callMethod ("setNetworkTimeout",
+ new Class[] { Executor.class, Integer.class },
+ new Object[] { executor, new Integer(milliseconds) });
+
+ }
+
+/* endif */
+
+ // JDBC 4.1
+ public int getNetworkTimeout() throws SQLException {
+ return ((Integer)callMethodRtnObj ("getNetworkTimeout")).intValue();
+ }
+
+ // JDBC 4.1
+ public String getSchema() throws SQLException {
+ return ((String)callMethodRtnObj ("getSchema"));
+ }
+
+
+ // JDBC 4.1
+ public void setSchema(String schema) throws SQLException {
+ callMethod ("setSchema",
+ new Class[] { String.class },
+ new Object[] { schema });
+
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDDatabaseMetaDataProxy.java b/jdbc40/com/ibm/as400/access/JDDatabaseMetaDataProxy.java
new file mode 100644
index 000000000..99062593f
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDDatabaseMetaDataProxy.java
@@ -0,0 +1,1591 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDDatabaseMetaDataProxy.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.lang.reflect.InvocationTargetException;
+import java.sql.ResultSet;
+/* ifdef JDBC40 */
+import java.sql.RowIdLifetime;
+/* endif */
+import java.sql.SQLException;
+
+
+
+class JDDatabaseMetaDataProxy
+extends AbstractProxyImpl
+implements java.sql.DatabaseMetaData
+{
+ static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
+
+
+ // Private data.
+
+ private JDConnectionProxy jdConnection_;
+ // The object that caused this object to be created.
+
+
+ /**
+ Constructs a JDDatabaseMetaDataProxy object.
+
+ @param connectionProxy The Connection object that caused this object to be created.
+ **/
+ public JDDatabaseMetaDataProxy (JDConnectionProxy jdConnection)
+ {
+ jdConnection_ = jdConnection;
+ }
+
+
+ public boolean allProceduresAreCallable ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("allProceduresAreCallable");
+ }
+
+ public boolean allTablesAreSelectable ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("allTablesAreSelectable");
+ }
+
+ private boolean callMethodRtnBool (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsBoolean (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a boolean.
+ private boolean callMethodRtnBool (String methodName, int arg)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (arg) })
+ .getReturnValueBoolean ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ private boolean callMethodRtnBool (String methodName,
+ Class[] argClasses,
+ Object[] argValues)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, methodName,
+ argClasses, argValues)
+ .getReturnValueBoolean ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return an int.
+ private int callMethodRtnInt (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsInt (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a ResultSet.
+ private JDResultSetProxy callMethodRtnRSet (String methodName)
+ throws SQLException
+ {
+ try {
+ JDResultSetProxy newResultSet = new JDResultSetProxy (jdConnection_);
+ return (JDResultSetProxy) connection_.callFactoryMethod (
+ pxId_, methodName, newResultSet);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ private JDResultSetProxy callMethodRtnRSet (String methodName,
+ Class[] argClasses,
+ Object[] argValues)
+ throws SQLException
+ {
+ try {
+ JDResultSetProxy newResultSet = new JDResultSetProxy (jdConnection_);
+ return (JDResultSetProxy) connection_.callFactoryMethod (
+ pxId_, methodName,
+ argClasses, argValues,
+ newResultSet);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ // Call a method, and return a String.
+ private String callMethodRtnStr (String methodName)
+ throws SQLException
+ {
+ try {
+ return (String) connection_.callMethodReturnsObject (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ private Object callMethodRtnObj (String methodName)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethodReturnsObject (pxId_, methodName);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@PDA jdbc40
+ Object callMethodRtnObj(String methodName, Class[] argClasses, Object[] argValues) throws SQLException
+ {
+ try
+ {
+ return connection_.callMethod(pxId_, methodName, argClasses, argValues).getReturnValue();
+ } catch (InvocationTargetException e)
+ {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public boolean dataDefinitionCausesTransactionCommit ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("dataDefinitionCausesTransactionCommit");
+ }
+
+
+ public boolean dataDefinitionIgnoredInTransactions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("dataDefinitionIgnoredInTransactions");
+ }
+
+
+
+// JDBC 2.0
+ public boolean deletesAreDetected (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("deletesAreDetected", resultSetType);
+ }
+
+
+ public boolean doesMaxRowSizeIncludeBlobs ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("doesMaxRowSizeIncludeBlobs");
+ }
+
+
+// JDBC 3.0
+ public ResultSet getAttributes (String catalog,
+ String schemaPattern,
+ String typeNamePattern,
+ String attributeNamePattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getAttributes",
+ new Class[] { String.class, String.class,
+ String.class,
+ String.class},
+ new Object[] { catalog, schemaPattern, typeNamePattern,
+ attributeNamePattern});
+ }
+
+
+ public ResultSet getBestRowIdentifier (String catalog,
+ String schema,
+ String table,
+ int scope,
+ boolean nullable)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getBestRowIdentifier",
+ new Class[] { String.class, String.class,
+ String.class,
+ Integer.TYPE, Boolean.TYPE },
+ new Object[] { catalog, schema, table,
+ new Integer (scope),
+ new Boolean (nullable) });
+ }
+
+
+ public ResultSet getCatalogs ()
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getCatalogs");
+ }
+
+ public String getCatalogSeparator ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getCatalogSeparator");
+ }
+
+
+ public String getCatalogTerm ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getCatalogTerm");
+ }
+
+ public ResultSet getColumnPrivileges (String catalog,
+ String schema,
+ String table,
+ String columnPattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getColumnPrivileges",
+ new Class[] { String.class, String.class,
+ String.class, String.class },
+ new Object[] { catalog, schema,
+ table, columnPattern });
+ }
+
+ public ResultSet getColumns (String catalog,
+ String schemaPattern,
+ String tablePattern,
+ String columnPattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getColumns",
+ new Class[] { String.class, String.class,
+ String.class, String.class },
+ new Object[] { catalog, schemaPattern,
+ tablePattern, columnPattern });
+ }
+
+
+// JDBC 2.0
+ public java.sql.Connection getConnection ()
+ throws SQLException
+ {
+ return jdConnection_;
+ }
+
+
+ public ResultSet getCrossReference (String primaryCatalog,
+ String primarySchema,
+ String primaryTable,
+ String foreignCatalog,
+ String foreignSchema,
+ String foreignTable)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getCrossReference",
+ new Class[] { String.class, String.class,
+ String.class, String.class,
+ String.class, String.class },
+ new Object[] { primaryCatalog, primarySchema,
+ primaryTable, foreignCatalog,
+ foreignSchema, foreignTable });
+ }
+
+
+// JDBC 3.0
+ public int getDatabaseMajorVersion ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getDatabaseMajorVersion");
+ }
+
+
+// JDBC 3.0
+ public int getDatabaseMinorVersion ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getDatabaseMinorVersion");
+ }
+
+
+ public String getDatabaseProductName ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getDatabaseProductName");
+ }
+
+
+ public String getDatabaseProductVersion ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getDatabaseProductVersion");
+ }
+
+
+ public int getDefaultTransactionIsolation ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getDefaultTransactionIsolation");
+ }
+
+
+ public int getDriverMajorVersion ()
+ {
+ try {
+ return callMethodRtnInt ("getDriverMajorVersion");
+ }
+ catch (SQLException e)
+ {
+ throw new InternalErrorException (InternalErrorException.UNEXPECTED_EXCEPTION, e);
+ }
+ }
+
+
+ public int getDriverMinorVersion ()
+ {
+ try {
+ return callMethodRtnInt ("getDriverMinorVersion");
+ }
+ catch (SQLException e)
+ {
+ throw new InternalErrorException (InternalErrorException.UNEXPECTED_EXCEPTION, e);
+ }
+ }
+
+
+ public String getDriverName ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getDriverName");
+ }
+
+
+ public String getDriverVersion ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getDriverVersion");
+ }
+
+
+ public ResultSet getExportedKeys (String catalog,
+ String schema,
+ String table)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getExportedKeys",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schema, table });
+ }
+
+
+ public String getExtraNameCharacters ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getExtraNameCharacters");
+ }
+
+
+ public String getIdentifierQuoteString ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getIdentifierQuoteString");
+ }
+
+
+ public ResultSet getImportedKeys (String catalog,
+ String schema,
+ String table)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getImportedKeys",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schema, table });
+ }
+
+
+ public ResultSet getIndexInfo (String catalog,
+ String schema,
+ String table,
+ boolean unique,
+ boolean approximate)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getIndexInfo",
+ new Class[] { String.class, String.class,
+ String.class, Boolean.TYPE,
+ Boolean.TYPE },
+ new Object[] { catalog, schema,
+ table, new Boolean (unique),
+ new Boolean (approximate) });
+ }
+
+
+// JDBC 3.0
+ public int getJDBCMajorVersion ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getJDBCMajorVersion");
+ }
+
+
+// JDBC 3.0
+ public int getJDBCMinorVersion ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getJDBCMinorVersion");
+ }
+
+
+ public int getMaxBinaryLiteralLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxBinaryLiteralLength");
+ }
+
+
+ public int getMaxCatalogNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxCatalogNameLength");
+ }
+
+
+ public int getMaxCharLiteralLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxCharLiteralLength");
+ }
+
+
+ public int getMaxColumnNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnNameLength");
+ }
+
+
+ public int getMaxColumnsInGroupBy ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnsInGroupBy");
+ }
+
+
+ public int getMaxColumnsInIndex ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnsInIndex");
+ }
+
+
+ public int getMaxColumnsInOrderBy ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnsInOrderBy");
+ }
+
+
+ public int getMaxColumnsInSelect ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnsInSelect");
+ }
+
+
+ public int getMaxColumnsInTable ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxColumnsInTable");
+ }
+
+
+ public int getMaxConnections ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxConnections");
+ }
+
+
+ public int getMaxCursorNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxCursorNameLength");
+ }
+
+
+ public int getMaxIndexLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxIndexLength");
+ }
+
+
+ public int getMaxProcedureNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxProcedureNameLength");
+ }
+
+
+ public int getMaxRowSize ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxRowSize");
+ }
+
+
+ public int getMaxSchemaNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxSchemaNameLength");
+ }
+
+
+ public int getMaxStatementLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxStatementLength");
+ }
+
+
+ public int getMaxStatements ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxStatements");
+ }
+
+
+ public int getMaxTableNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxTableNameLength");
+ }
+
+
+ public int getMaxTablesInSelect ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxTablesInSelect");
+ }
+
+
+ public int getMaxUserNameLength ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getMaxUserNameLength");
+ }
+
+
+ public String getNumericFunctions ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getNumericFunctions");
+ }
+
+
+ public ResultSet getPrimaryKeys (String catalog,
+ String schema,
+ String table)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getPrimaryKeys",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schema, table });
+ }
+
+
+ public ResultSet getProcedureColumns (String catalog,
+ String schemaPattern,
+ String procedurePattern,
+ String columnPattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getProcedureColumns",
+ new Class[] { String.class, String.class,
+ String.class, String.class },
+ new Object[] { catalog, schemaPattern,
+ procedurePattern, columnPattern });
+ }
+
+
+ public ResultSet getProcedures (String catalog,
+ String schemaPattern,
+ String procedurePattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getProcedures",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schemaPattern,
+ procedurePattern });
+ }
+
+
+ public String getProcedureTerm ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getProcedureTerm");
+ }
+
+
+// JDBC 3.0
+ public int getResultSetHoldability ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getResultSetHoldability");
+ }
+
+
+ public ResultSet getSchemas ()
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getSchemas");
+ }
+
+
+ public String getSchemaTerm ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getSchemaTerm");
+ }
+
+
+ public String getSearchStringEscape ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getSearchStringEscape");
+ }
+
+
+ public String getSQLKeywords ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getSQLKeywords");
+ }
+
+
+// JDBC 3.0
+ public int getSQLStateType ()
+ throws SQLException
+ {
+ return callMethodRtnInt ("getSQLStateType");
+ }
+
+
+ public String getStringFunctions ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getStringFunctions");
+ }
+
+
+// JDBC 3.0
+ public ResultSet getSuperTables (String catalog,
+ String schemaPattern,
+ String tableNamePattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getSuperTables",
+ new Class[] { String.class, String.class,
+ String.class},
+ new Object[] { catalog, schemaPattern,
+ tableNamePattern});
+ }
+
+
+// JDBC 3.0
+ public ResultSet getSuperTypes (String catalog,
+ String schemaPattern,
+ String typeNamePattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getSuperTypes",
+ new Class[] { String.class, String.class,
+ String.class},
+ new Object[] { catalog, schemaPattern,
+ typeNamePattern});
+ }
+
+
+
+ public String getSystemFunctions ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getSystemFunctions");
+ }
+
+
+ public ResultSet getTablePrivileges (String catalog,
+ String schemaPattern,
+ String tablePattern)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getTablePrivileges",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schemaPattern,
+ tablePattern });
+ }
+
+
+ public ResultSet getTables (String catalog,
+ String schemaPattern,
+ String tablePattern,
+ String tableTypes[])
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getTables",
+ new Class[] { String.class, String.class,
+ String.class, String[].class },
+ new Object[] { catalog, schemaPattern,
+ tablePattern, tableTypes });
+ }
+
+
+ public ResultSet getTableTypes ()
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getTableTypes");
+ }
+
+
+ public String getTimeDateFunctions ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getTimeDateFunctions");
+ }
+
+
+ public ResultSet getTypeInfo ()
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getTypeInfo");
+ }
+
+
+// JDBC 2.0
+ public ResultSet getUDTs (String catalog,
+ String schemaPattern,
+ String typeNamePattern,
+ int[] types)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getUDTs",
+ new Class[] { String.class, String.class,
+ String.class, int[].class },
+ new Object[] { catalog, schemaPattern,
+ typeNamePattern, types });
+ }
+
+
+ public String getURL ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getURL");
+ }
+
+
+ public String getUserName ()
+ throws SQLException
+ {
+ return callMethodRtnStr ("getUserName");
+ }
+
+
+ public ResultSet getVersionColumns (String catalog,
+ String schema,
+ String table)
+ throws SQLException
+ {
+ return callMethodRtnRSet ("getVersionColumns",
+ new Class[] { String.class, String.class,
+ String.class },
+ new Object[] { catalog, schema, table });
+ }
+
+
+// JDBC 2.0
+ public boolean insertsAreDetected (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("insertsAreDetected", resultSetType);
+ }
+
+
+ public boolean isCatalogAtStart ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isCatalogAtStart");
+ }
+
+
+ boolean isCatalogValid (String catalog)
+ throws SQLException
+ {
+ return callMethodRtnBool ("isCatalogValid",
+ new Class[] { String.class },
+ new Object[] { catalog });
+ }
+
+
+ public boolean isReadOnly ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("isReadOnly");
+ }
+
+
+// JDBC 3.0
+ public boolean locatorsUpdateCopy ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("locatorsUpdateCopy");
+ }
+
+
+ public boolean nullPlusNonNullIsNull ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("nullPlusNonNullIsNull");
+ }
+
+
+ public boolean nullsAreSortedAtEnd ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("nullsAreSortedAtEnd");
+ }
+
+
+ public boolean nullsAreSortedAtStart ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("nullsAreSortedAtStart");
+ }
+
+
+ public boolean nullsAreSortedHigh ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("nullsAreSortedHigh");
+ }
+
+
+ public boolean nullsAreSortedLow ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("nullsAreSortedLow");
+ }
+
+
+// JDBC 2.0
+ public boolean othersDeletesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("othersDeletesAreVisible", resultSetType);
+ }
+
+
+// JDBC 2.0
+ public boolean othersInsertsAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("othersInsertsAreVisible", resultSetType);
+ }
+
+
+// JDBC 2.0
+ public boolean othersUpdatesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("othersUpdatesAreVisible", resultSetType);
+ }
+
+
+// JDBC 2.0
+ public boolean ownDeletesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("ownDeletesAreVisible", resultSetType);
+ }
+
+
+// JDBC 2.0
+ public boolean ownInsertsAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("ownInsertsAreVisible", resultSetType);
+ }
+
+
+// JDBC 2.0
+ public boolean ownUpdatesAreVisible (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("ownUpdatesAreVisible", resultSetType);
+ }
+
+
+ public boolean storesLowerCaseIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesLowerCaseIdentifiers");
+ }
+
+
+ public boolean storesLowerCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesLowerCaseQuotedIdentifiers");
+ }
+
+
+ public boolean storesMixedCaseIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesMixedCaseIdentifiers");
+ }
+
+
+ public boolean storesMixedCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesMixedCaseQuotedIdentifiers");
+ }
+
+
+ public boolean storesUpperCaseIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesUpperCaseIdentifiers");
+ }
+
+
+ public boolean storesUpperCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("storesUpperCaseQuotedIdentifiers");
+ }
+
+
+ public boolean supportsAlterTableWithAddColumn ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsAlterTableWithAddColumn");
+ }
+
+
+ public boolean supportsAlterTableWithDropColumn ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsAlterTableWithDropColumn");
+ }
+
+
+ public boolean supportsANSI92EntryLevelSQL ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsANSI92EntryLevelSQL");
+ }
+
+
+ public boolean supportsANSI92FullSQL ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsANSI92FullSQL");
+ }
+
+
+ public boolean supportsANSI92IntermediateSQL ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsANSI92IntermediateSQL");
+ }
+
+
+// JDBC 2.0
+ public boolean supportsBatchUpdates ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsBatchUpdates");
+ }
+
+
+ public boolean supportsCatalogsInDataManipulation ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCatalogsInDataManipulation");
+ }
+
+
+ public boolean supportsCatalogsInIndexDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCatalogsInIndexDefinitions");
+ }
+
+
+ public boolean supportsCatalogsInPrivilegeDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCatalogsInPrivilegeDefinitions");
+ }
+
+
+ public boolean supportsCatalogsInProcedureCalls ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCatalogsInProcedureCalls");
+ }
+
+
+ public boolean supportsCatalogsInTableDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCatalogsInTableDefinitions");
+ }
+
+
+ public boolean supportsColumnAliasing ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsColumnAliasing");
+ }
+
+
+ public boolean supportsConvert ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsConvert");
+ }
+
+
+ public boolean supportsConvert (int fromType, int toType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsConvert",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (fromType),
+ new Integer (toType) });
+ }
+
+
+ public boolean supportsCoreSQLGrammar ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCoreSQLGrammar");
+ }
+
+
+ public boolean supportsCorrelatedSubqueries ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsCorrelatedSubqueries");
+ }
+
+
+ public boolean supportsDataDefinitionAndDataManipulationTransactions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsDataDefinitionAndDataManipulationTransactions");
+ }
+
+
+ public boolean supportsDataManipulationTransactionsOnly ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsDataManipulationTransactionsOnly");
+ }
+
+
+ public boolean supportsDifferentTableCorrelationNames ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsDifferentTableCorrelationNames");
+ }
+
+
+ public boolean supportsExpressionsInOrderBy ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsExpressionsInOrderBy");
+ }
+
+
+ public boolean supportsExtendedSQLGrammar ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsExtendedSQLGrammar");
+ }
+
+
+ public boolean supportsFullOuterJoins ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsFullOuterJoins");
+ }
+
+
+// JDBC 3.0
+ public boolean supportsGetGeneratedKeys ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsGetGeneratedKeys");
+ }
+
+
+ public boolean supportsGroupBy ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsGroupBy");
+ }
+
+
+ public boolean supportsGroupByBeyondSelect ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsGroupByBeyondSelect");
+ }
+
+
+ public boolean supportsGroupByUnrelated ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsGroupByUnrelated");
+ }
+
+
+ public boolean supportsIntegrityEnhancementFacility ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsIntegrityEnhancementFacility");
+ }
+
+
+ public boolean supportsLikeEscapeClause ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsLikeEscapeClause");
+ }
+
+
+ public boolean supportsLimitedOuterJoins ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsLimitedOuterJoins");
+ }
+
+
+ public boolean supportsMinimumSQLGrammar ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMinimumSQLGrammar");
+ }
+
+
+ public boolean supportsMixedCaseIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMixedCaseIdentifiers");
+ }
+
+
+ public boolean supportsMixedCaseQuotedIdentifiers ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMixedCaseQuotedIdentifiers");
+ }
+
+
+// JDBC 3.0
+ public boolean supportsMultipleOpenResults ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMultipleOpenResults");
+ }
+
+
+ public boolean supportsMultipleResultSets ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMultipleResultSets");
+ }
+
+
+ public boolean supportsMultipleTransactions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsMultipleTransactions");
+ }
+
+
+// JDBC 3.0
+ public boolean supportsNamedParameters ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsNamedParameters");
+ }
+
+
+ public boolean supportsNonNullableColumns ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsNonNullableColumns");
+ }
+
+
+ public boolean supportsOpenCursorsAcrossCommit ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOpenCursorsAcrossCommit");
+ }
+
+
+ public boolean supportsOpenCursorsAcrossRollback ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOpenCursorsAcrossRollback");
+ }
+
+
+ public boolean supportsOpenStatementsAcrossCommit ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOpenStatementsAcrossCommit");
+ }
+
+
+ public boolean supportsOpenStatementsAcrossRollback ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOpenStatementsAcrossRollback");
+ }
+
+
+ public boolean supportsOrderByUnrelated ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOrderByUnrelated");
+ }
+
+
+ public boolean supportsOuterJoins ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsOuterJoins");
+ }
+
+
+ public boolean supportsPositionedDelete ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsPositionedDelete");
+ }
+
+
+ public boolean supportsPositionedUpdate ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsPositionedUpdate");
+ }
+
+
+// JDBC 2.0
+ public boolean supportsResultSetConcurrency (int resultSetType, int resultSetConcurrency)
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsResultSetConcurrency",
+ new Class[] { Integer.TYPE, Integer.TYPE },
+ new Object[] { new Integer (resultSetType),
+ new Integer (resultSetConcurrency) });
+ }
+
+
+// JDBC 3.0
+ public boolean supportsResultSetHoldability (int resultSetHoldability)
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsResultSetHoldability",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (resultSetHoldability)});
+ }
+
+
+// JDBC 2.0
+ public boolean supportsResultSetType (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsResultSetType", resultSetType);
+ }
+
+
+// JDBC 3.0
+ public boolean supportsSavepoints ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSavepoints");
+ }
+
+
+ public boolean supportsSchemasInDataManipulation ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSchemasInDataManipulation");
+ }
+
+
+ public boolean supportsSchemasInIndexDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSchemasInIndexDefinitions");
+ }
+
+
+ public boolean supportsSchemasInPrivilegeDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSchemasInPrivilegeDefinitions");
+ }
+
+
+ public boolean supportsSchemasInProcedureCalls ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSchemasInProcedureCalls");
+ }
+
+
+ public boolean supportsSchemasInTableDefinitions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSchemasInTableDefinitions");
+ }
+
+
+ public boolean supportsSelectForUpdate ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSelectForUpdate");
+ }
+
+
+ public boolean supportsStatementPooling()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsStatementPooling");
+ }
+
+
+ public boolean supportsStoredProcedures ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsStoredProcedures");
+ }
+
+
+ public boolean supportsSubqueriesInComparisons ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSubqueriesInComparisons");
+ }
+
+
+ public boolean supportsSubqueriesInExists ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSubqueriesInExists");
+ }
+
+
+ public boolean supportsSubqueriesInIns ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSubqueriesInIns");
+ }
+
+
+ public boolean supportsSubqueriesInQuantifieds ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsSubqueriesInQuantifieds");
+ }
+
+
+ public boolean supportsTableCorrelationNames ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsTableCorrelationNames");
+ }
+
+
+ public boolean supportsTransactionIsolationLevel (int transactionIsolationLevel)
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsTransactionIsolationLevel", transactionIsolationLevel);
+ }
+
+
+ public boolean supportsTransactions ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsTransactions");
+ }
+
+
+ public boolean supportsUnion ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsUnion");
+ }
+
+
+ public boolean supportsUnionAll ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("supportsUnionAll");
+ }
+
+
+ // This method is not required by java.sql.DatabaseMetaData,
+ // but it is used by the JDBC testcases, and is implemented
+ // in the public class.
+ public String toString ()
+ {
+ try {
+ return (String) connection_.callMethodReturnsObject (pxId_, "toString");
+ }
+ catch (InvocationTargetException e) {
+ throw ProxyClientConnection.rethrow (e);
+ }
+ }
+
+
+// JDBC 2.0
+ public boolean updatesAreDetected (int resultSetType)
+ throws SQLException
+ {
+ return callMethodRtnBool ("updatesAreDetected", resultSetType);
+ }
+
+
+ public boolean usesLocalFilePerTable ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("usesLocalFilePerTable");
+ }
+
+
+ public boolean usesLocalFiles ()
+ throws SQLException
+ {
+ return callMethodRtnBool ("usesLocalFiles");
+ }
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.DatabaseMetaData" };
+ }
+
+
+ //@PDA jdbc40
+ public boolean autoCommitFailureClosesAllResultSets() throws SQLException
+ {
+ return callMethodRtnBool("autoCommitFailureClosesAllResultSets");
+ }
+
+
+ //@PDA 550
+ public ResultSet getClientInfoProperties() throws SQLException
+ {
+ return callMethodRtnRSet("getClientInfoProperties");
+ }
+
+/* ifdef JDBC40 */
+
+ //@PDA jdbc40
+ public RowIdLifetime getRowIdLifetime() throws SQLException
+ {
+ return (RowIdLifetime) callMethodRtnObj("getRowIdLifetime");
+ }
+/* endif */
+
+ //@PDA jdbc40
+ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException
+ {
+ return callMethodRtnRSet("getSchemas", new Class[] {String.class, String.class}, new Object[] {catalog, schemaPattern});
+ }
+
+ // @PDA jdbc40
+ public boolean providesQueryObjectGenerator() throws SQLException
+ {
+ return callMethodRtnBool("providesQueryObjectGenerator");
+ }
+
+ //@PDA jdbc40
+ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException
+ {
+ return callMethodRtnBool("supportsStoredFunctionsUsingCallSyntax");
+ }
+
+ //@pdd removde getFunctionParameters. It was renamed to getFunctionColumns()
+
+ //@PDA jdbc40
+ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException
+ {
+ return callMethodRtnRSet ("getFunctions",
+ new Class[] { String.class, String.class, String.class },
+ new Object[] { catalog, schemaPattern, functionNamePattern });
+ }
+
+ //@pda 550
+ public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException
+ {
+ return callMethodRtnRSet ("getFunctionColumns",
+ new Class[] { String.class, String.class, String.class, String.class },
+ new Object[] { catalog, schemaPattern, functionNamePattern, columnNamePattern });
+ }
+
+ // JDBC 4.1
+ public boolean generatedKeyAlwaysReturned() throws SQLException {
+ return callMethodRtnBool("generatedKeyAlwaysReturned");
+ }
+
+
+ // JDBC 4.1
+ public ResultSet getPseudoColumns(String catalog, String schemaPattern,
+ String tableNamePattern, String columnNamePattern)
+ throws SQLException {
+ return callMethodRtnRSet ("getPseudoColumns",
+ new Class[] { String.class, String.class, String.class, String.class },
+ new Object[] { catalog, schemaPattern, tableNamePattern, columnNamePattern });
+
+ }
+
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDError.java b/jdbc40/com/ibm/as400/access/JDError.java
new file mode 100644
index 000000000..ccd4fc119
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDError.java
@@ -0,0 +1,896 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDError.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;
+
+/* ifdef JDBC40 */
+import java.sql.ClientInfoStatus;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLDataException;
+/* endif */
+import java.sql.SQLException;
+/* ifdef JDBC40 */
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.sql.SQLInvalidAuthorizationSpecException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLSyntaxErrorException;
+import java.sql.SQLTimeoutException;
+import java.sql.SQLTransactionRollbackException;
+import java.util.Map;
+/* endif */
+
+import java.sql.SQLWarning;
+
+
+
+/**
+The JDError class provides access to all of the error and
+warning SQL states and message string resources.
+**/
+//
+// Implementation note:
+//
+// When adding or changing an error message or SQL state, there
+// are places that you need to add or change:
+//
+// 1. A String constant defined to be equal to the SQL state.
+// 2. A resource in JDMRI.properties, named JD + SQL state.
+//
+final class JDError
+{
+ // Constants for SQL states.
+ static final String EXC_ACCESS_MISMATCH = "42505";
+ static final String EXC_ATTRIBUTE_VALUE_INVALID = "HY024";
+ static final String EXC_BUFFER_LENGTH_INVALID = "HY090";
+ static final String EXC_CHAR_CONVERSION_INVALID = "22524";
+ static final String EXC_CCSID_INVALID = "22522";
+ static final String EXC_COLUMN_NOT_FOUND = "42703";
+ static final String EXC_CONCURRENCY_INVALID = "HY108";
+ static final String EXC_CONNECTION_NONE = "08003";
+ static final String EXC_CONNECTION_REJECTED = "08004";
+ static final String EXC_CONNECTION_UNABLE = "08001";
+ static final String EXC_COMMUNICATION_LINK_FAILURE = "08S01"; // @F2A
+ static final String EXC_CURSOR_NAME_AMBIGUOUS = "3C000";
+ static final String EXC_CURSOR_NAME_INVALID = "34000";
+ static final String EXC_CURSOR_POSITION_INVALID = "HY109";
+ static final String EXC_CURSOR_STATE_INVALID = "24000";
+ static final String EXC_DATA_TYPE_INVALID = "HY004";
+ static final String EXC_DATA_TYPE_MISMATCH = "07006";
+ static final String EXC_DESCRIPTOR_INDEX_INVALID = "07009";
+ static final String EXC_FUNCTION_NOT_SUPPORTED = "IM001";
+ static final String EXC_FUNCTION_SEQUENCE = "HY010";
+ static final String EXC_INTERNAL = "HY000";
+ static final String EXC_MAX_STATEMENTS_EXCEEDED = "HY014";
+ static final String EXC_OPERATION_CANCELLED = "HY008";
+ static final String EXC_PARAMETER_COUNT_MISMATCH = "07001";
+ static final String EXC_PARAMETER_TYPE_INVALID = "HY105";
+ static final String EXC_SCALE_INVALID = "HY094";
+ static final String EXC_SERVER_ERROR = "HY001";
+ static final String EXC_SYNTAX_BLANK = "43617";
+ static final String EXC_SYNTAX_ERROR = "42601";
+ static final String EXC_TXN_STATE_INVALID = "25000"; // @E1C
+ static final String EXC_SQL_STATEMENT_TOO_LONG = "54001"; // @E9A
+ static final String EXC_SAVEPOINT_INVALID_IN_CONTEXT = "3B001"; // @E10a
+ static final String EXC_SAVEPOINT_ALREADY_EXISTS = "3B501"; // @E10a
+ static final String EXC_SAVEPOINT_DOES_NOT_EXIST = "3B502"; // @E10a
+ static final String EXC_RDB_DOES_NOT_EXIST = "42705"; // @J2a
+ static final String EXC_XML_PARSING_ERROR = "2200M"; // @xml2
+
+ static final String WARN_ATTRIBUTE_VALUE_CHANGED = "01608";
+ static final String WARN_EXTENDED_DYNAMIC_DISABLED = "01H11";
+ static final String WARN_OPTION_VALUE_CHANGED = "01S02";
+ static final String WARN_PACKAGE_CACHE_DISABLED = "01H12";
+ static final String WARN_PROPERTY_EXTRA_IGNORED = "01H20";
+ static final String WARN_TXN_COMMITTED = "01H30";
+ static final String WARN_URL_EXTRA_IGNORED = "01H10";
+ static final String WARN_URL_SCHEMA_INVALID = "01H13";
+ static final String WARN_1000_OPEN_STATEMENTS = "01G00"; //@K1A
+
+
+
+ static String lastServerSQLState_ = null;
+
+ static boolean jdk14 = false;
+ static {
+ jdk14 = JVMInfo.isJDK14();
+ }
+
+/**
+Private constructor to prevent instantiation. All methods in
+this class are static.
+**/
+ private JDError ()
+ {
+ }
+
+
+
+/**
+Returns the reason text based on a SQL state.
+
+@param sqlState the SQL State.
+@return Reason - error description.
+**/
+ static final String getReason (String sqlState)
+ {
+ return AS400JDBCDriver.getResource ("JD" + sqlState);
+ }
+
+
+
+// @E2C
+/**
+Returns the message text for the last operation on the IBM i system.
+
+@param connection Connection to the system.
+@param id Id for the last operation.
+@param returnCode The return code from the last operation.
+@return Reason - error description.
+**/
+ private static String getReason (AS400JDBCConnection connection,
+ int id,
+ int returnCode) // @E2A
+ {
+ try
+ {
+ // Check to see if the caller wants second level text, too.
+ boolean secondLevelText = connection.getProperties().equals (JDProperties.ERRORS, JDProperties.ERRORS_FULL);
+
+ // Get the message text from the system. We also retrieve
+ // the SQL state at this time to save a trip to the system.
+ int orsBitmap = DBBaseRequestDS.ORS_BITMAP_RETURN_DATA
+ + DBBaseRequestDS.ORS_BITMAP_SQLCA
+ + DBBaseRequestDS.ORS_BITMAP_MESSAGE_ID
+ + DBBaseRequestDS.ORS_BITMAP_FIRST_LEVEL_TEXT;
+ if (secondLevelText)
+ orsBitmap += DBBaseRequestDS.ORS_BITMAP_SECOND_LEVEL_TEXT;
+
+ DBSQLResultSetDS request = null; //@P0A
+ DBReplyRequestedDS reply = null; //@P0A
+ try //@P0A
+ {
+ request = DBDSPool.getDBSQLResultSetDS ( //@P0C
+ DBSQLResultSetDS.FUNCTIONID_SEND_RESULTS_SET,
+ id, orsBitmap, 0);
+
+ reply = connection.sendAndReceive (request, id); //@P0C
+ DBReplySQLCA sqlca = reply.getSQLCA(); // @E2A
+
+ // Build up the error description.
+ StringBuffer errorDescription = new StringBuffer ();
+ errorDescription.append ("[");
+ errorDescription.append (reply.getMessageId());
+ errorDescription.append ("] ");
+
+ // If pre-V5R4:
+ // If the return code is +-438 (from an SQL stored procedure) or @E4A
+ // +-443 (from an external stored procedure) AND errd[3] is 0, then @E4A @E6C
+ // an error was signalled by the stored procedure itself. @E4A
+ boolean textAppended = false; // @E6A
+ int absReturnCode = Math.abs(returnCode); // @E4A
+
+ if ((absReturnCode == 438) || (absReturnCode == 443) && // @E2A @E4C @E5C @E6C
+ (connection.getVRM() < JDUtilities.vrm540)) //@25955a
+ {
+ try //@25955a
+ {
+ if (sqlca.getErrd (4) == 0) //@F1C // @E6A
+ {
+ if (absReturnCode == 438) // @E2A @E4C @E5C
+ {
+ errorDescription.append(sqlca.getErrmc(connection.converter_)); // @E2A @P0C
+ textAppended = true; // @E8A
+ }
+ else if (absReturnCode == 443) // @E5A
+ {
+ errorDescription.append(sqlca.getErrmc(6, connection.converter_)); // @E5A @P0C
+ textAppended = true; // @E8A
+ }
+ } // @E6A
+ }
+ catch(Exception e) { // In some circumstances the getErrmc() can throw a NegativeArraySizeException or ArrayIndexOutOfBoundsException. @25955a
+ JDTrace.logException(null, e.getMessage(), e); // just trace it
+ }
+ }
+
+ // Otherwise, get the text directly from the reply. // @E6A
+ if (textAppended == false) // @E2A @E6C
+ {
+ errorDescription.append (reply.getFirstLevelMessageText());
+ if (secondLevelText)
+ {
+ errorDescription.append (" ");
+ errorDescription.append (reply.getSecondLevelMessageText ());
+ }
+ } // @E2A
+
+ // Get the SQL state and remember it for the next
+ // call to getSQLState().
+ lastServerSQLState_ = sqlca.getSQLState (connection.converter_); // @E2C @P0C
+ if (lastServerSQLState_ == null)
+ lastServerSQLState_ = EXC_SERVER_ERROR;
+
+ return errorDescription.toString ();
+ }
+ finally
+ {
+ if (request != null) { request.returnToPool(); request = null; }
+ if (reply != null) { reply.returnToPool(); reply = null; }
+ }
+ }
+ catch (DBDataStreamException e)
+ {
+ return getReason (EXC_INTERNAL);
+ }
+ catch (SQLException e)
+ {
+ return getReason (EXC_INTERNAL);
+ }
+ }
+
+
+
+/**
+Returns the SQL state for the last operation on the IBM i system.
+
+@param connection Connection to the system.
+@param id Id for the last operation.
+@return The SQL state.
+**/
+ private static String getSQLState (AS400JDBCConnection connection,
+ int id)
+ {
+ // If the SQL state was retrieved by a previous call to
+ // getReason(), then use that.
+ if (lastServerSQLState_ != null)
+ {
+ String sqlState = lastServerSQLState_;
+ lastServerSQLState_ = null;
+ return sqlState;
+ }
+
+ // Otherwise, go to the system to get it.
+ try
+ {
+ int orsBitmap = DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SQLCA;
+
+ DBSQLResultSetDS request = null; //@P0A
+ DBReplyRequestedDS reply = null; //@P0A
+ try //@P0A
+ {
+ request = DBDSPool.getDBSQLResultSetDS (DBSQLResultSetDS.FUNCTIONID_SEND_RESULTS_SET, id, orsBitmap, 0); //@P0C
+
+ reply = connection.sendAndReceive (request, id); //@P0C
+
+ String sqlState = reply.getSQLCA ().getSQLState (connection.converter_); //@P0C
+
+ if (sqlState == null)
+ sqlState = EXC_SERVER_ERROR;
+
+ return sqlState;
+ }
+ finally
+ {
+ if (request != null) { request.returnToPool(); request = null; }
+ if (reply != null) { reply.returnToPool(); reply = null; }
+ }
+ }
+ catch (DBDataStreamException e)
+ {
+ return getReason (EXC_INTERNAL);
+ }
+ catch (SQLException e)
+ {
+ return getReason (EXC_INTERNAL);
+ }
+ }
+
+
+
+/**
+Returns an SQL warning based on an error in the
+error table.
+
+@param sqlState The SQL State.
+**/
+ public static SQLWarning getSQLWarning (String sqlState)
+ {
+ // The DB2 for IBM i SQL CLI manual says that
+ // we should set the native error code to -99999
+ // when the driver generates the warning.
+ //
+ String reason = getReason(sqlState);
+ SQLWarning warning = new SQLWarning (reason, sqlState, -99999);
+
+ if (JDTrace.isTraceOn ()) // @J3a
+ {
+ // @J3a
+ String message = "Posting warning, sqlState: " + sqlState // @J3a
+ + " reason: " + reason // @J3a
+ + " vendor code -99999"; // @J3a
+ JDTrace.logException(null, message, warning); // @J3a
+ } // @J3a
+
+ return warning;
+ }
+
+
+
+/**
+Returns an SQL warning based on information
+retrieved from the IBM i system.
+
+@param connection connection to the system.
+@param id id for the last operation.
+@param errorClass error class from the system reply.
+@param returnCode return code from the system reply.
+**/
+ public static SQLWarning getSQLWarning (AS400JDBCConnection connection,
+ int id,
+ int errorClass,
+ int returnCode)
+ {
+ String reason = getReason (connection, id, returnCode);
+ String state = getSQLState (connection, id);
+
+ SQLWarning warning = new SQLWarning (reason, state, returnCode); // @E2C
+
+ if (JDTrace.isTraceOn ()) // @J3a
+ {
+ // @J3a
+ String message = "Posting warning, id: " + id // @J3a
+ + " error class: " + errorClass // @J3a
+ + " return code: " + returnCode // @J3a
+ + " reason: " + reason // @J3a
+ + " state: " + state; // @J3a
+ JDTrace.logException(connection, message, warning); // @J3a
+ } // @J3a
+
+ return warning;
+ }
+
+
+
+
+/**
+Throws an SQL exception based on an error in the
+error table.
+
+@param sqlState The SQL State.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (String sqlState)
+ throws SQLException
+ {
+ // @J4 - changed this method to call the method that takes an object ID. Don't
+ // know why the same code was in two places. A null object ID is handled
+ // by both this class and JDTrace.
+ JDError.throwSQLException((Object)null, sqlState);
+ }
+
+
+// @J3 new method
+/**
+Throws an SQL exception based on an error in the
+error table.
+
+@param Object The object throwing the exception. This can be null.
+@param sqlState The SQL State.
+
+
+@exception SQLException Always.
+**/
+ public static SQLException throwSQLException (Object thrower, String sqlState)
+ throws SQLException
+ {
+ // The DB2 for IBM i SQL CLI manual says that
+ // we should set the native error code to -99999
+ // when the driver generates the error.
+ //
+ String reason = getReason(sqlState);
+/* ifdef JDBC40 */
+ SQLException e = createSQLExceptionSubClass(reason, sqlState, -99999); //@PDA jdbc40
+
+/* endif */
+/* ifndef JDBC40
+ SQLException e = new SQLException (reason, sqlState, -99999);
+ endif */
+ if (JDTrace.isTraceOn ())
+ {
+ String message = "Throwing exception, sqlState: " + sqlState
+ + " reason: " + reason
+ + " vendor code -99999";
+ JDTrace.logException(thrower, message, e);
+ }
+
+ throw e;
+ }
+
+
+
+/**
+Throws an SQL exception based on an error in the
+error table and dumps an internal exception stack
+trace for debugging purposes.
+
+@param sqlState The SQL State.
+@param e The internal exception.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (String sqlState, Exception e)
+ throws SQLException
+ {
+ // @J4 - changed this method to call the method that takes an object ID.
+ // This method can be removed once all code that uses is has been updated
+ // to call the method that takes a reference to the thrower. That is, once
+ // all jdbc classes have been changed from
+ // JDError.throwSQLException(state, e);
+ // to
+ // JDError.throwSQLException(this, state, e);
+
+ JDError.throwSQLException(null, sqlState, e);
+ }
+
+
+/**
+Throws an SQL exception based on an error in the
+error table and dumps an internal exception stack
+trace for debugging purposes.
+
+@param sqlState The SQL State.
+@param message The message text.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (String sqlState, String message)
+ throws SQLException
+ {
+ JDError.throwSQLException(null, sqlState, message);
+ }
+
+
+/**
+Throws an SQL exception based on an error in the
+error table and dumps an internal exception stack
+trace for debugging purposes.
+
+@param sqlState The SQL State.
+@param message The message text.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (Object thrower, String sqlState, String message)
+ throws SQLException
+ {
+ String reason = getReason(sqlState);
+ StringBuffer buffer = new StringBuffer(reason);
+ if (message != null)
+ {
+ buffer.append(" (");
+ buffer.append(message);
+ buffer.append(')');
+ }
+
+ // The DB2 for IBM i SQL CLI manual says that
+ // we should set the native error code to -99999
+ // when the driver generates the error.
+ //
+
+/* ifdef JDBC40 */
+ SQLException e2 = createSQLExceptionSubClass(buffer.toString(), sqlState, -99999); //@PDA jdbc40
+
+/* endif */
+/* ifndef JDBC40
+ SQLException e2 = new SQLException (buffer.toString(), sqlState, -99999);
+ endif */
+ if (JDTrace.isTraceOn ())
+ {
+ String m2 = "Throwing exception. Message text: "+message;
+ JDTrace.logInformation(thrower, m2);
+
+ m2 = "Throwing exception. Actual exception: "
+ + buffer.toString()
+ + " sqlState: " + sqlState
+ + " vendor code -99999";
+ JDTrace.logException(thrower, m2, e2);
+ }
+
+ throw e2;
+ }
+
+
+// @J4 new method. It has all the code from the method that takes a state and an
+// exception. What is added is a reference to the thrower so we know
+// who is throwing the exception.
+/**
+Throws an SQL exception based on an error in the
+error table and dumps an internal exception stack
+trace for debugging purposes.
+
+@param sqlState The SQL State.
+@param e The internal exception.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (Object thrower, String sqlState, Exception e)
+ throws SQLException
+ {
+ // Dump the internal exception stack trace if
+ // trace is on.
+ // @J3d if (JDTrace.isTraceOn ()) { // @D0A
+ // @J3d synchronized (DriverManager.class) { // @D0A
+ // @J3d e.printStackTrace (DriverManager.getLogWriter());
+ // @J3d } // @D0A
+ // @J3d } // @D0A
+
+ String reason = getReason(sqlState);
+ StringBuffer buffer = new StringBuffer(reason); // @E3A
+ if (e != null) {
+ buffer.append(" ("); // @E3A
+ String message = e.getMessage(); // @E3A
+ if (message != null) // @E3A
+ buffer.append(message); // @E3A
+ else
+ // @E3A
+ buffer.append(e.getClass()); // @E3A
+ buffer.append(')'); // @E7A
+ }
+
+ // The DB2 for IBM i SQL CLI manual says that
+ // we should set the native error code to -99999
+ // when the driver generates the error.
+ //
+/* ifdef JDBC40 */
+ SQLException e2 = createSQLExceptionSubClass(buffer.toString(), sqlState, -99999); //@PDA jdbc40
+
+/* endif */
+/* ifndef JDBC40
+ SQLException e2 = new SQLException (buffer.toString(), sqlState, -99999); // @E3C
+ endif */
+ if (JDTrace.isTraceOn ()) // @J3a
+ { // @J3a
+ String m2 = "Throwing exception. Original exception: "; // @J3a
+ JDTrace.logException(thrower, m2, e); // @J3a
+ // @J3a
+ m2 = "Throwing exception. Actual exception: " // @J3a
+ + buffer.toString() // @J3a
+ + " sqlState: " + sqlState // @J3a
+ + " vendor code -99999"; // @J3a
+ JDTrace.logException(thrower, m2, e2); // @J3a
+ } // @J3a
+
+ //
+ // Set the cause for JDK 1.4 and later
+ //
+ if (jdk14) {
+ if (e != null) {
+ e2.initCause(e);
+ }
+ }
+ throw e2;
+ }
+
+/**
+Throws an SQL exception based on an error in the
+error table and dumps an internal exception stack
+trace for debugging purposes.
+
+@param thrower The object that threw the exception.
+@param sqlState The SQL State.
+@param e The internal exception.
+@param m A message for the exception
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (Object thrower, String sqlState, Exception e, String m)
+ throws SQLException
+ {
+
+ String reason = getReason(sqlState);
+ StringBuffer buffer = new StringBuffer(reason);
+ buffer.append(" (");
+ String message = e.getMessage();
+ if (message != null)
+ buffer.append(message);
+ else
+ buffer.append(e.getClass());
+ buffer.append(", ");
+ buffer.append(m);
+ buffer.append(')');
+
+ // The DB2 for IBM i SQL CLI manual says that
+ // we should set the native error code to -99999
+ // when the driver generates the error.
+ //
+/* ifdef JDBC40 */
+ SQLException e2 = createSQLExceptionSubClass(buffer.toString(), sqlState, -99999); //@PDA jdbc40
+
+/* endif */
+/* ifndef JDBC40
+ SQLException e2 = new SQLException (buffer.toString(), sqlState, -99999);
+ endif */
+ if (JDTrace.isTraceOn ())
+ {
+ String m2 = "Throwing exception. Original exception: ";
+ JDTrace.logException(thrower, m2, e);
+
+ m2 = "Throwing exception. Actual exception: "
+ + buffer.toString()
+ + " sqlState: " + sqlState
+ + " vendor code -99999";
+ JDTrace.logException(thrower, m2, e2);
+ }
+ if (e != null) {
+ try {
+ e2.initCause(e);
+ } catch (Throwable t) {}
+ }
+ throw e2;
+ }
+
+
+/**
+Throws an SQL exception based on information
+retrieved from the IBM i system.
+
+@param connection connection to the system.
+@param id id for the last operation.
+@param errorClass error class from the system reply.
+@param returnCode return code from the system reply.
+
+@exception SQLException Always.
+**/
+ public static void throwSQLException (AS400JDBCConnection connection,
+ int id,
+ int errorClass,
+ int returnCode)
+ throws SQLException
+ {
+ // @J4 code moved to the method that takes a reference to the object
+ // that is throwing the exception. This method can be removed
+ // once all code that uses is has been updated to call the
+ // method that takes a reference to the thrower. That is, once
+ // all jdbc classes have been changed from
+ // JDError.throwSQLException(connection, id, errorClass, returnCode);
+ // to
+ // JDError.throwSQLException(this, connection, id, errorClass, returnCode);
+
+ JDError.throwSQLException(null, connection, id, errorClass, returnCode);
+ }
+
+
+
+// @J4 new method. It has all the code from the method that takes a connection,
+// and the error stuff. What is added is a reference to the thrower so we know
+// who is throwing the exception.
+/**
+Throws an SQL exception based on information
+retrieved from the system.
+
+@param connection connection to the system.
+@param id id for the last operation.
+@param errorClass error class from the system reply.
+@param returnCode return code from the system reply.
+
+@exception SQLException Always.
+**/
+ public static SQLException throwSQLException (Object thrower,
+ AS400JDBCConnection connection,
+ int id,
+ int errorClass,
+ int returnCode)
+ throws SQLException
+ {
+ String reason = getReason(connection, id, returnCode);
+ String state = getSQLState(connection, id);
+
+/* ifdef JDBC40 */
+ SQLException e = createSQLExceptionSubClass(reason, state, returnCode); //@PDA jdbc40
+
+/* endif */
+/* ifndef JDBC40
+ SQLException e = new SQLException (reason, state, returnCode); // @E2C
+ endif */
+ if (JDTrace.isTraceOn ()) // @J3a
+ { // @J3a
+ String message = "Throwing exception, id: " + id // @J3a
+ + " error class: " + errorClass // @J3a
+ + " return code: " + returnCode // @J3a
+ + " reason: " + reason // @J3a
+ + " state: " + state; // @J3a
+ JDTrace.logException(thrower, connection, message, e); // @J3a
+ } // @J3a
+
+ throw e;
+ }
+
+
+ public static SQLException throwSQLException(Object thrower, SQLException exception)
+ throws SQLException {
+
+ String reason = exception.getMessage();
+ String state = exception.getSQLState();
+ int returnCode = exception.getErrorCode();
+
+/* ifdef JDBC40 */
+
+ SQLException e = createSQLExceptionSubClass(reason, state, returnCode);
+/* endif */
+
+/* ifndef JDBC40
+ SQLException e = new SQLException(reason, state, returnCode);
+ endif */
+ try {
+ e.setNextException(exception);
+ } catch (Exception setError) {
+ // Just ignore
+ }
+ if (JDTrace.isTraceOn()) {
+ String message = "Throwing exception, " + " return code: " + returnCode
+ + " reason: " + reason + " state: " + state;
+ JDTrace.logException(thrower, message, e);
+ }
+
+ throw e;
+ }
+
+
+
+
+ //@PDA jdbc40
+ /**
+ Throws an SQLClientInfoException exception based on an error in the
+ error table and dumps an internal exception stack
+ trace for debugging purposes.
+
+ @param thrower The object that is throwing the exception.
+ @param sqlState The SQL State.
+ @param e The internal exception.
+
+ @exception SQLClientInfoException Always.
+ **/
+ //
+ //@pdc jdbc40 merge public static void throwSQLClientInfoException (Object thrower, String sqlState, Exception e, Map
+ String serverJobIdentifier = ((JDConnectionProxy)connection).getServerJobIdentifier();
+
DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver
+ * and the maximum length that may be specified for each property.
+ * SQLException
. If the driver
+ * generates a SQLException
, the value specified was not set on the
+ * connection.
+ *
+ *
+ * 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.
+ * 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.
+ *
+ *
+ * DatabaseMetaData.getClientInfoProperties
+ * method to determine the client info properties supported by the driver.
+ *
+ *
+ *
+ *
+ * Properties
object that contains the name and current value of
+ * each of the client info properties supported by the driver.
+ * 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 ((AS400JDBCConnection)actualConnection_).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
+ {
+ return ((AS400JDBCConnection)actualConnection_).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
+ {
+ return actualConnection_.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
+ {
+ return actualConnection_.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
+ {
+ return ((AS400JDBCConnection)actualConnection_).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
+ {
+ return ((AS400JDBCConnection)actualConnection_).createStruct(typeName, attributes);
+ }
+
+
+/* ifdef JDBC40 */
+ // JDBC 4.1
+ public void abort(Executor executor) throws SQLException {
+
+ ((AS400JDBCConnection)actualConnection_).abort(executor);
+ }
+/* endif */
+
+/* ifdef JDBC40 */
+ public int getNetworkTimeout() throws SQLException {
+ return ((AS400JDBCConnection)actualConnection_).getNetworkTimeout();
+
+ }
+/* endif */
+
+ // JDBC 4.1
+ public String getSchema() throws SQLException {
+ return ((AS400JDBCConnection)actualConnection_).getSchema();
+ }
+
+ public void setSchema(String schema) throws SQLException {
+ ((AS400JDBCConnection)actualConnection_).setSchema(schema);
+ }
+
+/* ifdef JDBC40 */
+ // JDBC 4.1
+ public void setNetworkTimeout(Executor executor, int milliseconds)
+ throws SQLException {
+ ((AS400JDBCConnection)actualConnection_).setNetworkTimeout(executor, milliseconds);
+
+ }
+/* endif */
+
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDNClobProxy.java b/jdbc40/com/ibm/as400/access/JDNClobProxy.java
new file mode 100644
index 000000000..f7cc87664
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDNClobProxy.java
@@ -0,0 +1,244 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDNClobProxy.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) 2006-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.io.Writer;
+import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Clob;
+/* ifdef JDBC40 */
+import java.sql.NClob;
+/* endif */
+import java.sql.SQLException;
+
+
+//@PDA jdbc40 new class
+
+/**
+The JDNClobProxy class provides access to character large
+objects. The data is valid only within the current
+transaction.
+**/
+class JDNClobProxy
+extends AbstractProxyImpl
+/* ifdef JDBC40 */
+implements NClob
+/* endif */
+{
+
+
+ // Copied from JDError:
+ private static final String EXC_FUNCTION_NOT_SUPPORTED = "IM001";
+
+
+
+ public InputStream getAsciiStream ()
+ throws SQLException
+ {
+ try {
+ JDInputStreamProxy newStream = new JDInputStreamProxy ();
+ return (JDInputStreamProxy) connection_.callFactoryMethod (
+ pxId_, "getAsciiStream", newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public Reader getCharacterStream ()
+ throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getCharacterStream",
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public String getSubString (long start, int length)
+ throws SQLException
+ {
+ try {
+ return (String) connection_.callMethod (pxId_, "getSubString",
+ new Class[] { Long.TYPE, Integer.TYPE },
+ new Object[] { new Long (start),
+ new Integer (length) })
+ .getReturnValue();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public long length ()
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "length")
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public long position (String pattern, long start)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "position",
+ new Class[] { String.class, Long.TYPE },
+ new Object[] { pattern, new Long (start) })
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ public long position (Clob pattern, long start)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "position",
+ new Class[] { Clob.class, Long.TYPE },
+ new Object[] { pattern, new Long (start) })
+ .getReturnValueLong ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public OutputStream setAsciiStream (long pos)
+ throws SQLException
+ {
+ try
+ {
+ JDOutputStreamProxy newStream = new JDOutputStreamProxy ();
+ return (JDOutputStreamProxy) connection_.callFactoryMethod (pxId_, "setAsciiStream",
+ new Class[] { Long.TYPE},
+ new Object[] { new Long(pos)},
+ newStream);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public Writer setCharacterStream (long pos)
+ throws SQLException
+ {
+
+ try
+ {
+ JDWriterProxy newWriter = new JDWriterProxy ();
+ return (JDWriterProxy) connection_.callFactoryMethod (pxId_, "setCharacterStream",
+ new Class[] { Long.TYPE},
+ new Object[] { new Long(pos)},
+ newWriter);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public int setString (long pos, String str)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "setString",
+ new Class[] { Long.TYPE, String.class},
+ new Object[] { new Long(pos), str})
+ .getReturnValueInt ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public int setString (long pos, String str, int offset, int len)
+ throws SQLException
+ {
+ try {
+ return connection_.callMethod (pxId_, "setString",
+ new Class[] { Long.TYPE, String.class, Integer.TYPE, Integer.TYPE},
+ new Object[] { new Long(pos), str, new Integer(offset), new Integer(len)})
+ .getReturnValueInt ();
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public void truncate (long len)
+ throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, "truncate",
+ new Class[] { Long.TYPE,},
+ new Object[] { new Long(len)} );
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+
+ public void free() throws SQLException
+ {
+ try {
+ connection_.callMethod (pxId_, "free");
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ public Reader getCharacterStream(long pos, long length) throws SQLException
+ {
+ try {
+ JDReaderProxy newReader = new JDReaderProxy ();
+ return (JDReaderProxy) connection_.callFactoryMethod (
+ pxId_, "getCharacterStream",
+ new Class[] { Long.TYPE, Long.TYPE},
+ new Object[] { new Long(pos), new Long(length)},
+ newReader);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+}
diff --git a/jdbc40/com/ibm/as400/access/JDParameterMetaDataProxy.java b/jdbc40/com/ibm/as400/access/JDParameterMetaDataProxy.java
new file mode 100644
index 000000000..fbfde7cae
--- /dev/null
+++ b/jdbc40/com/ibm/as400/access/JDParameterMetaDataProxy.java
@@ -0,0 +1,147 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// JTOpen (IBM Toolbox for Java - OSS version)
+//
+// Filename: JDParameterMetaDataProxy.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.lang.reflect.InvocationTargetException;
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
+
+
+
+/**
+ResultSet
object as a
+ * java.io.Reader
object.
+ * It is intended for use when
+ * accessing NCHAR
,NVARCHAR
+ * and LONGNVARCHAR
columns.
+ *
+ * @param columnName the name of the column
+ * @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
+ * @exception SQLException if a database access error occurs
+ */
+ public Reader getNCharacterStream(String columnName) throws SQLException
+ {
+ return getNCharacterStream (findColumn (columnName));
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column is 1, the second is 2, ...
+ * @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 NClob getNClob(int columnIndex) throws SQLException
+ {
+ try {
+ JDNClobProxy newClob = new JDNClobProxy ();
+ return (JDNClobProxy) connection_.callFactoryMethod (pxId_,
+ "getNClob",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(columnIndex) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * 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 the name of the column from which to retrieve the value
+ * @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 occurs
+ */
+/* ifdef JDBC40 */
+ public NClob getNClob(String columnName) throws SQLException
+ {
+ return getNClob (findColumn (columnName));
+ }
+/* endif */
+
+
+ //@pda jdbc40
+ /**
+ * 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 columnIndex the first column is 1, the second is 2, ...
+ * @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 columnIndex) throws SQLException
+ {
+ return (String) callMethodRtnObj ("getNString",
+ new Class[] { Integer.TYPE},
+ new Object[] { new Integer (columnIndex) });
+ }
+
+
+ //@pda jdbc40
+ /**
+ * 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 the SQL name of the 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(String columnName) throws SQLException
+ {
+ return getNString (findColumn (columnName));
+ }
+
+
+ //@pda jdbc40
+/* ifdef JDBC40 */
+ public RowId getRowId(int columnIndex) throws SQLException
+ {
+ try {
+ JDRowIdProxy newClob = new JDRowIdProxy ();
+ return (JDRowIdProxy) connection_.callFactoryMethod (pxId_,
+ "getRowId",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(columnIndex) },
+ newClob);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+
+ //@pda jdbc40
+ public RowId getRowId(String columnName) throws SQLException
+ {
+ return getRowId(findColumn (columnName));
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML(int columnIndex) throws SQLException
+ {
+ try {
+ JDSQLXMLProxy newXML = new JDSQLXMLProxy ();
+ return (JDSQLXMLProxy) connection_.callFactoryMethod (pxId_,
+ "getSQLXML",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer(columnIndex) },
+ newXML);
+ }
+ catch (InvocationTargetException e) {
+ throw JDConnectionProxy.rethrow1 (e);
+ }
+ }
+
+ //@pda jdbc40
+ public SQLXML getSQLXML(String columnName) throws SQLException
+ {
+ return getSQLXML(findColumn (columnName));
+ }
+/* endif */
+
+ //@pda jdbc40
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (x == null)
+ reader = null;
+ else
+ reader = new SerializableReader (x, Math.max(0,(int)length));
+ callMethod ("updateNCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class, Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ reader, new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+
+ }
+
+ //@PDA jdbc40
+ public void updateNCharacterStream(String columnName, Reader x, long length) throws SQLException
+ {
+ updateNCharacterStream (findColumn (columnName), x, length);
+ }
+
+ //@PDA jdbc40
+/* ifdef JDBC40 */
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException
+ {
+ callMethod ("updateNClob",
+ new Class[] { String.class, NClob.class },
+ new Object[] { new Integer (columnIndex),
+ nClob });
+ }
+
+ //@PDA jdbc40
+ public void updateNClob(String columnName, NClob nClob) throws SQLException
+ {
+ updateNClob (findColumn (columnName), nClob);
+
+ }
+/* endif */
+
+ //@pda jdbc40
+ public void updateNString(int columnIndex, String nString) throws SQLException
+ {
+ callMethod ("updateNString",
+ new Class[] { Integer.TYPE, String.class },
+ new Object[] { new Integer (columnIndex),
+ nString });
+ }
+
+ //@PDA jdbc40
+ public void updateNString(String columnName, String nString) throws SQLException
+ {
+ updateNString (findColumn (columnName), nString);
+ }
+
+/* ifdef JDBC40 */
+ //@PDA jdbc40
+ public void updateRowId(int columnIndex, RowId x) throws SQLException
+ {
+ callMethod ("updateRowId",
+ new Class[] { String.class, RowId.class },
+ new Object[] { new Integer (columnIndex),
+ x });
+ }
+
+ //@pda jdbc40
+ public void updateRowId(String columnName, RowId x) throws SQLException
+ {
+ updateRowId (findColumn (columnName), x);
+ }
+
+
+ //@pda jdbc40
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException
+ {
+ callMethod ("updateSQLXML",
+ new Class[] { String.class, SQLXML.class },
+ new Object[] { new Integer (columnIndex),
+ xmlObject });
+ }
+
+ //@pda jdbc40
+ public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException
+ {
+ updateSQLXML(findColumn(columnName), xmlObject);
+ }
+
+/* endif */
+
+ //@pda jdbc40
+ protected String[] getValidWrappedList()
+ {
+ return new String[] { "java.sql.ResultSet" }; //@pdc user cannot cast to AS400JDBCResultSet
+ }
+
+ //@PDA jdbc40
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null || x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ iStream,
+ new Long (length) });
+ }
+
+
+ //@PDA jdbc40
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ updateAsciiStream (findColumn (columnLabel), x, length);
+ }
+
+
+ //@PDA jdbc40
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null || x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException
+ {
+ updateBinaryStream (findColumn (columnLabel), x, length);
+ }
+
+ //@PDA jdbc40
+ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException
+ {
+ InputStream iStream;
+ if (inputStream == null || inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateBlob",
+ new Class[] { Integer.TYPE, InputStream.class,
+ Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ iStream,
+ new Long (length) });
+ }
+
+ //@PDA jdbc40
+ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException
+ {
+ updateBlob (findColumn (columnLabel), inputStream, length);
+ }
+
+ //@PDA jdbc40
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException
+ {
+ try {
+ SerializableReader reader;
+ if (x == null)
+ reader = null;
+ else
+ reader = new SerializableReader (x, Math.max(0,(int)length));
+ callMethod ("updateCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class, Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ reader, new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateCharacterStream (findColumn (columnLabel), reader, length);
+ }
+
+ //@PDA jdbc40
+ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (reader == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (reader, Math.max(0,(int)length));
+ callMethod ("updateClob",
+ new Class[] { Integer.TYPE, Reader.class, Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ sReader, new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateClob (findColumn (columnLabel), reader, length);
+ }
+
+
+
+ //@PDA jdbc40
+ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (reader == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (reader, Math.max(0,(int)length));
+ callMethod ("updateNClob",
+ new Class[] { Integer.TYPE, Reader.class, Long.TYPE },
+ new Object[] { new Integer (columnIndex),
+ sReader, new Long (length) });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException
+ {
+ updateNClob (findColumn (columnLabel), reader, length);
+ }
+
+ //@PDA jdbc40
+ public boolean isClosed () throws SQLException
+ {
+ return callMethodRtnBool ("isClosed");
+ }
+
+
+ //@pda jdbc40
+ public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null || x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateAsciiStream",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (columnIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException
+ {
+ updateAsciiStream (findColumn (columnLabel), x);
+ }
+
+
+ //@PDA jdbc40
+ public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException
+ {
+ InputStream iStream;
+ if (x == null || x instanceof Serializable)
+ iStream = x;
+ else {
+ try {
+ iStream = new SerializableInputStream (x);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateBinaryStream",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (columnIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException
+ {
+ updateBinaryStream (findColumn (columnLabel), x);
+
+ }
+
+
+ //@PDA jdbc40
+ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException
+ {
+ InputStream iStream;
+ if ( inputStream== null || inputStream instanceof Serializable)
+ iStream = inputStream;
+ else {
+ try {
+ iStream = new SerializableInputStream (inputStream);
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+ callMethod ("updateBlob",
+ new Class[] { Integer.TYPE, InputStream.class },
+ new Object[] { new Integer (columnIndex),
+ iStream });
+ }
+
+
+ //@PDA jdbc40
+ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException
+ {
+ updateBlob (findColumn (columnLabel), inputStream);
+ }
+
+
+ //@PDA jdbc40
+ public void updateCharacterStream(int columnIndex, Reader x) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (x == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (x);
+ callMethod ("updateCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (columnIndex), sReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException
+ {
+ updateCharacterStream(findColumn (columnLabel), reader);
+ }
+
+
+ //@PDA jdbc40
+ public void updateClob(int columnIndex, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (reader == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (reader);
+ callMethod ("updateClob",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (columnIndex), sReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+
+ //@PDA jdbc40
+ public void updateClob(String columnLabel, Reader reader) throws SQLException
+ {
+ updateClob(findColumn (columnLabel), reader);
+ }
+
+ //@PDA jdbc40
+ public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (x == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (x);
+ callMethod ("updateNCharacterStream",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (columnIndex), sReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+
+ }
+
+ //@PDA jdbc40
+ public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException
+ {
+ updateNCharacterStream(findColumn (columnLabel), reader);
+ }
+
+ //@PDA jdbc40
+ public void updateNClob(int columnIndex, Reader reader) throws SQLException
+ {
+ try {
+ SerializableReader sReader;
+ if (reader == null)
+ sReader = null;
+ else
+ sReader = new SerializableReader (reader);
+ callMethod ("updateNClob",
+ new Class[] { Integer.TYPE, Reader.class },
+ new Object[] { new Integer (columnIndex), sReader });
+ }
+ catch (java.io.IOException e) {
+ SQLException throwException = new SQLException(e.getMessage());
+ try {
+ throwException.initCause(e);
+ } catch (Throwable t) {}
+ throw throwException;
+ }
+ }
+
+ //@PDA jdbc40
+ public void updateNClob(String columnLabel, Reader reader) throws SQLException
+ {
+ updateNClob(findColumn (columnLabel), reader);
+ }
+
+
+
+ public void updateDB2Default(int columnIndex) throws SQLException
+ {
+ callMethod ("updateDB2Default",
+ new Class[] { Integer.TYPE },
+ new Object[] { new Integer (columnIndex) });
+
+ }
+
+ public void updateDBDefault(int columnIndex) throws SQLException
+ {
+ updateDB2Default(columnIndex);
+ }
+
+
+
+
+/* ifdef JDBC40 */
+
+ public isWrapperFor
on the wrapped object. If this does not
+ * implement the interface and is not a wrapper, return false. This method
+ * should be implemented as a low-cost operation compared to
+ * unwrap
so that callers can use this method to avoid
+ * expensive unwrap
calls that may fail. If this method
+ * returns true then calling unwrap
with the same argument
+ * should succeed.
+ *
+ * @param iface
+ * a Class defining an interface.
+ * @return true if this implements the interface or directly or indirectly
+ * wraps an object that does.
+ * @throws java.sql.SQLException
+ * if an error occurs while determining whether this is a
+ * wrapper for an object with the given interface.
+ */
+/* ifdef JDBC40 */
+ public boolean isWrapperFor(Class> iface) throws SQLException
+ {
+ if (iface == null)
+ return false;
+
+ String[] validWrappedList = getValidWrappedList();
+ for (int i = 0; i < validWrappedList.length; i++)
+ {
+ if (iface.getName().equals(validWrappedList[i]))
+ return true;
+ }
+
+ return false;
+ }
+/* endif */
+ /**
+ * Returns an object that implements the given interface to allow access to
+ * non-standard methods, or standard methods not exposed by the proxy.
+ *
+ * If the receiver implements the interface then the result is the receiver
+ * or a proxy for the receiver. If the receiver is a wrapper and the wrapped
+ * object implements the interface then the result is the wrapped object or
+ * a proxy for the wrapped object. Otherwise return the the result of
+ * calling unwrap
recursively on the wrapped object or a
+ * proxy for that result. If the receiver is not a wrapper and does not
+ * implement the interface, then an SQLException
is thrown.
+ *
+ * @param iface
+ * A Class defining an interface that the result must implement.
+ * @return an object that implements the interface. May be a proxy for the
+ * actual implementing object.
+ * @throws java.sql.SQLException
+ * If no object found that implements the interface
+ */
+/* ifdef JDBC40 */
+ public