src.com.ibm.as400.access.AS400JDBCPreparedStatementImpl Maven / Gradle / Ivy
Show all versions of jt400-jdk9 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// 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;
import java.sql.SQLWarning;
/* 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 JDBC42
import java.sql.SQLType;
import java.sql.JDBCType;
endif */
/* ifdef JDBC40
import java.sql.SQLXML;
import java.sql.SQLFeatureNotSupportedException;
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;
/**
*
* 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 AS400JDBCPreparedStatementImpl extends AS400JDBCPreparedStatement {
static final String copyright2 = "Copyright (C) 1997-2006 International Business Machines Corporation and others.";
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 boolean preserveParameters_ = false;
private boolean saveParameterValues_ = false; // save the parameters so that can be
// reset in a Client Affinities environment
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;
}
};
/**
* 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.
**/
AS400JDBCPreparedStatementImpl(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) {
try {
close();
} catch (Exception e2) {
// ignore any nested exceptions
}
throw e;
}
executed_ = false;
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.getBatchableObject();
// @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
sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
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_.getConverter()); // @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*/
int variableDataLength = 0; //@L9A
disableRllCompression_ = false; //@L9A
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) {
// Save the values so that can be restored later
if (saveParameterValues_) {
if (parameterRow_ != null) {
parameterRow_.saveValues();
}
}
// 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++;
variableDataLength+=2; //@L9A
} 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
} else {
size = parameterRow_.getLength(i + 1); /* @X5A */
} // @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
int thisParameterOffset = 0; /*@X4A*/
if (useVariableFieldInsertCompression) {
if (sqlData instanceof SQLVariableCompressible) {
// @K3A write the compressed bytes for the field.
thisParameterOffset = rowDataOffset + parameterOffset;
int written = ((SQLVariableCompressible) sqlData)
.convertToCompressedBytes(
parameterMarkerData.getRawBytes(),
thisParameterOffset,
ccsidConverter);
variableDataLength += written; //@L9A
parameterOffset += written;
} else {
thisParameterOffset = rowDataOffset + parameterOffset;
sqlData.convertToRawBytes(
parameterMarkerData.getRawBytes(), thisParameterOffset, ccsidConverter);
// Increment by the length of the parameter
parameterOffset += parameterLengths_[i];
}
} else {
thisParameterOffset = rowDataOffset
+ parameterOffsets_[i];
sqlData.convertToRawBytes(
parameterMarkerData.getRawBytes(), thisParameterOffset, ccsidConverter);
}
// Need to check for truncation from convert
// Blob truncation not caught at set time if set
// using input stream @09A
// if (ConvTable.isMixedCCSID(ccsidConverter.getCcsid()) ||
// sqlData instanceof SQLBlob ) // @trnc
// this
// is
// not caught at
// setX() time
// @H2C
boolean checkRawBytes = testDataTruncation(i + 1, sqlData); // @trnc
if (checkRawBytes) {
sqlData.validateRawTruncatedData(parameterMarkerData.getRawBytes(), thisParameterOffset, ccsidConverter);
}
}
// @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);
// Determine if enough space was saved by VFC to disable rll compression
// We will disable if at least 80 % of the data was VFC data
// This means that 20 % of the data can still be compressed using RLL
// It is still possible then when compression is on, that the client
// may decide not to send the compressed data if the compression
// is large enough. //@L9A
if ( variableDataLength > (80 * parametersLength / 100 )) {
disableRllCompression_ = true;
}
}
} 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 If a database error occurs.
*/
/*@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_) {
JDServerRow newParameterRow = new JDServerRow(connection_, id_,
reply.getParameterMarkerFormat(), settings_);
if (preserveParameters_ && (parameterRow_ != null)) {
newParameterRow.restoreSavedParameters(parameterRow_);
}
parameterRow_ = newParameterRow;
}
}
/**
* 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
}
public boolean execute(String sql, int [] columns) throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return false; // @B1A
}
public boolean execute(String sql, String [] columnNames) 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;
}
public int executeUpdate(String sql, int[] columns)
throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return 0;
}
public int executeUpdate(String sql, String[] columnNames)
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.
*
*
* 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 = extendedColumnDescriptors_; // @G6A@P6C
// If we have extendedDescriptors, send a ConvTable to convert them, else
// pass null // @G6A
if (extendedDescriptors != null) // @G6A
{
// @G6A
convTable = connection_.getConverter(); // @G6A
} // @G6A
return new AS400JDBCResultSetMetaData(connection_.getCatalog(),
resultSetConcurrency_, cursor_.getName(), resultRow_,
extendedDescriptors, convTable, connection_); // @in1 // @G6A
}
}
/* Validate the parameter index for this PreparedStatement object */
/* It has this name to avoid calling the validateParameterIndex */
/* method in AS400JDBCCallableStatement which does not account */
/* for stored procedure output parameters */
void validatePSParameterIndex(int param) throws SQLException {
int parameterCount = getParameterCount();
if (param > parameterCount) {
JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID, param+">"+parameterCount);
}
if ( param < 1) {
JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID, param+"<1");
}
}
// @G4A
// Return the class name of a parameter for ParameterMetaData support.
String getParameterClassName(int param) throws SQLException {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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();
}
}
//
// Return the ccsid of a parameter for ParameterMetaData support.
// @V8A
int getParameterCcsid(int param) throws SQLException {
validatePSParameterIndex(param);
synchronized (internalLock_) {
checkOpen();
if (useReturnValueParameter_) // @G8a
{
// @G8a
if (param == 1) // @G8a
return 0; // return value is a number which does not have a CCSID
else
// @G8a
param--; // @G8a
} // @G8a
return parameterRow_.getCCSID(param);
}
}
// @G4A
// Return the type name of a parameter for ParameterMetaData support.
String getParameterTypeName(int param) throws SQLException {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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 {
validatePSParameterIndex(param);
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.
validatePSParameterIndex(parameterIndex);
// 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
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(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.
validatePSParameterIndex(parameterIndex);
// 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: "
+ Trace.toHexString(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.
validatePSParameterIndex(parameterIndex);
// 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.
*
* 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.
validatePSParameterIndex(parameterIndex);
// 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
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(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();
validatePSParameterIndex(parameterIndex);
// 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
}
// 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
sqlType == SQLData.NCLOB_LOCATOR || //@pda jdbc40
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);
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();
validatePSParameterIndex(parameterIndex);
// 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);
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.
* @return True, if the caller should validate that the raw bytes are valid.
**/
/*@X4C*/
private boolean testDataTruncation(int parameterIndex, SQLData data)
throws SQLException // @trunc
{
// Moved logic to connection to be shared with AS400JdbcResultSet
return connection_.testDataTruncation(this, null, parameterIndex, true, data, sqlStatement_);
}
// @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
// JDBC40DOC /**
// JDBC40DOC * Sets the designated parameter to the given java.sql.RowId
object. The
// JDBC40DOC * driver converts this to a SQL ROWID
value when it sends it
// JDBC40DOC * to the database
// JDBC40DOC *
// JDBC40DOC * @param parameterIndex The parameter index (1-based).
// JDBC40DOC * @param x the parameter value
// JDBC40DOC * @throws SQLException if a database access error occurs
// JDBC40DOC *
// JDBC40DOC */
/* 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 The parameter index (1-based).
* @param value
* the parameter value
* @throws SQLException If a database error occurs.
* 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 The parameter index (1-based).
* @param value
* the parameter value
* @param length
* the number of characters in the parameter data.
* @throws SQLException If a database error occurs.
* 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
// JDBC40DOC /**
// JDBC40DOC * Sets the designated parameter to a java.sql.NClob
object. The driver converts this to a
// JDBC40DOC * SQL NCLOB
value when it sends it to the database.
// JDBC40DOC * @param parameterIndex The parameter index (1-based).
// JDBC40DOC * @param value the parameter value
// JDBC40DOC * @throws SQLException if the driver does not support national
// JDBC40DOC * character sets; if the driver can detect that a data conversion
// JDBC40DOC * error could occur ; or if a database access error occurs
// JDBC40DOC */
/* 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 The parameter index (1-based).
* @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 error occurs.
* 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 The parameter index (1-based).
* @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 error occurs.
* 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 The parameter index (1-based).
* @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 error occurs.
* 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
// JDBC40DOC /**
// JDBC40DOC * Sets the designated parameter to the given java.sql.SQLXML
object.
// JDBC40DOC * @param parameterIndex The parameter index (1-based).
// JDBC40DOC * @param xmlObject a SQLXML
object that maps an SQL XML
value
// JDBC40DOC * @throws SQLException if a database access error occurs
// JDBC40DOC */
/* 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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* @param parameterIndex The parameter index (1-based).
* @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 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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* @param parameterIndex The parameter index (1-based).
* @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 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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* @param parameterIndex The parameter index (1-based).
* @param reader
* the 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);
}
/* initialize the array of parameter names */
void initializeParameterNames() throws SQLException {
boolean isProcedure = (sqlStatement_.getProcedure() != null);
int count = 0;
if (parameterNames_ == null) {
// 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;
} else {
if (isProcedure) {
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;
} /* catch SQLException processing names */
} /* for parameterNumber */
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;
}
} finally {
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);
}
}
}
}
// @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 (parameterNames_ == null) {
initializeParameterNames();
}
// If we have a cache created, try to find the column name in it.
// 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;
}
// 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;
}
/**
* Return the name of the parameter for a stored procedure call.
* @param parm the parameter number to get the name for
* @return the parameter name.
* @throws SQLException If a database error occurs.
*/
public String getDB2ParameterName(int parm) throws SQLException {
synchronized (internalLock_) {
checkOpen();
validatePSParameterIndex(parm);
parm = parm - 1;
if (useReturnValueParameter_) {
parm = parm - 1;
}
if (parameterNames_ == null) {
initializeParameterNames();
}
if ((parm >= 0) && (parm < parameterNames_.length)) {
return parameterNames_[parm];
} else {
JDError.throwSQLException(this, JDError.EXC_DESCRIPTOR_INDEX_INVALID,"INTERNAL_ERROR");
return null;
}
}
}
// @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.
validatePSParameterIndex(parameterIndex);
// 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, SQLData.ALL_READER_BYTES);// new ConvTableReader(x, 819, 0,
// LOB_BLOCK_SIZE), null, -2); //@readerlen
// -2 flag to read all of reader bytes
} else {
sqlData.set(x, null, SQLData.ALL_READER_BYTES);// 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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* @param parameterIndex The parameter index (1-based).
* @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 PreparedStatement
*/
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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* @param parameterIndex The parameter index (1-based).
* @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 PreparedStatement
*/
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 The parameter index (1-based).
* @param inputStream
* An object that contains the data to set the parameter value to.
* @throws SQLException If a database error occurs.
* 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,
*
*/
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.
validatePSParameterIndex(parameterIndex);
// 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, SQLData.ALL_READER_BYTES); // @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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of setCharacterStream
* which takes a length parameter.
*
* @param parameterIndex The parameter index (1-based).
* @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
*/
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
*
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of setClob
which
* takes a length parameter.
*
* @param parameterIndex The parameter index (1-based).
* @param reader
* An object that contains the data to set the parameter value to.
* @throws SQLException If a database error occurs.
* 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
*
*/
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.
*
*
* Note: This stream object can either be a standard Java stream object
* or your own subclass that implements the standard interface.
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of
* setNCharacterStream
which takes a length parameter.
*
* @param parameterIndex The parameter index (1-based).
* @param value
* the parameter value
* @throws SQLException If a database error occurs.
* 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
*/
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
*
* Note: Consult your JDBC driver documentation to determine if it
* might be more efficient to use a version of setNClob
which
* takes a length parameter.
*
* @param parameterIndex The parameter index (1-based).
* @param reader
* An object that contains the data to set the parameter value to.
* @throws SQLException If a database error occurs.
* 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
*/
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);
}
/**
* Sets the value of the designated parameter with the given object. If the second
* argument is an InputStream then the stream must contain the number of bytes
* specified by scaleOrLength. If the second argument is a Reader then the reader
* must contain the number of characters specified by scaleOrLength. If these
* conditions are not true the driver will generate a SQLException when the
* prepared statement is executed.
*
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 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.
*
Note that this method may be used to pass database-specific abstract data types.
*
* @param parameterIndex - the first parameter is 1, the second is 2, ...
* @param x - the object containing the input parameter value
* @param targetSqlType - the SQL type to be sent to the database. The scale argument may
* further qualify this type.
* @param scaleOrLength - for java.sql.JDBCType.DECIMAL or java.sql.JDBCType.NUMERIC
* types, this is the number of digits after the decimal point. For Java Object types
* InputStream and Reader, this is the length of the data in the stream or reader.
* For all other types, this value will be ignored.
* @throws 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 or if the Java Object specified by x
* is an InputStream or Reader object and the value of the scale parameter is
* less than zero
*/
public void setObject(int parameterIndex,
Object x,
/* ifdef JDBC42
SQLType
endif*/
/* ifndef JDBC42 */
Object
/* endif */
targetSqlType,
int scaleOrLength)
throws SQLException {
int intType = mapSQLType(targetSqlType);
setObject(parameterIndex, x, intType, scaleOrLength);
}
/**
* converts an SQLType to its corresponding java.sql.Types value
*/
int mapSQLType(
/* ifdef JDBC42
SQLType
endif*/
/* ifndef JDBC42 */
Object
/* endif */
targetSqlType ) throws SQLException {
/* ifdef JDBC42
if (targetSqlType instanceof JDBCType) {
return targetSqlType.getVendorTypeNumber();
}
throw new SQLFeatureNotSupportedException("targetSqlType="+targetSqlType);
endif */
/* ifndef JDBC42 */
return 0;
/* endif */
}
/**
* Sets the value of the designated parameter with the given object. This method
* is similar to setObject(int parameterIndex, Object x, SQLType targetSqlType,
* int scaleOrLength), except that it assumes a scale of zero.
* @param parameterIndex - the first parameter is 1, the second is 2, ...
* @param x - the object containing the input parameter value
* @param targetSqlType - the SQL type to be sent to the database parameterIndex
* @throws 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
*/
public void setObject(int parameterIndex,
Object x,
/* ifdef JDBC42
SQLType
endif*/
/* ifndef JDBC42 */
Object
/* endif */
targetSqlType)
throws SQLException {
int intType = mapSQLType(targetSqlType);
setObject(parameterIndex, x, intType);
}
/**
* Executes the SQL statement in this PreparedStatement object, which
* must be an SQL Data Manipulation Language (DML) statement, such as
* INSERT, UPDATE or DELETE; or an SQL statement that returns nothing,
* such as a DDL statement.
*
This method should be used when the returned row count may exceed Integer.MAX_VALUE.
* @return either (1) the row count for SQL Data Manipulation Language (DML) statements or
* (2) 0 for SQL statements that return nothing
* @throws SQLException - if a database access error occurs; this method is called on a
* closed PreparedStatement or the SQL statement returns a ResultSet object
*/
public long executeLargeUpdate() throws SQLException {
return (long) executeUpdate();
}
public long executeLargeUpdate(String sql) throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return 0;
}
public long executeLargeUpdate(String sql,
int autoGeneratedKeys)
throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return 0;
}
public long executeLargeUpdate(String sql,
int[] columnIndexes)
throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return 0;
}
public long executeLargeUpdate(String sql,
String[] columnNames) throws SQLException {
JDError.throwSQLException(this, JDError.EXC_FUNCTION_SEQUENCE);
return 0;
}
/**
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
{
super.checkOpen();
if (connectionReset_) {
// Any exception from the prepare will just get thrown
preserveParameters_ = true;
// Make sure the existing parameters are saved before we prepared again
if (parameterRow_ != null) {
parameterRow_.saveValues();
}
resultRow_ = commonPrepare(sqlStatement_);
connectionReset_ = false;
}
}
void setConnectionReset(boolean reset) {
descriptorHandle_ = 0;
super.setConnectionReset(reset);
}
void setSaveParameterValues(boolean saveParameterValues) {
saveParameterValues_ = saveParameterValues;
}
}