deep-c-rsc/JCGO/sunawt/fix_sql/sun/jdbc/odbc/JdbcOdbcPreparedStatement.java

3513 lines
142 KiB
Java

/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
*/
/*
* @(#)JdbcOdbcPreparedStatement.java 1.39 01/07/30
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
//----------------------------------------------------------------------------
//
// Module: JdbcOdbcPreparedStatement.java
//
// Description: Impementation of the PreparedStatement interface class
//
// Product: JDBCODBC (Java DataBase Connectivity using
// Open DataBase Connectivity)
//
// Author: Karl Moss
//
// Date: March, 1996
//
//----------------------------------------------------------------------------
package sun.jdbc.odbc;
import java.io.Reader;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.math.*;
import java.sql.*;
public class JdbcOdbcPreparedStatement
extends JdbcOdbcStatement
implements java.sql.PreparedStatement {
//====================================================================
// Public methods
//====================================================================
//--------------------------------------------------------------------
// Constructor
// Perform any necessary initialization.
//--------------------------------------------------------------------
public JdbcOdbcPreparedStatement (
JdbcOdbcConnectionInterface con)
{
super (con);
}
//--------------------------------------------------------------------
// initialize
// Initialize the result set object. Give the ODBC API interface
// object, the connection handle, and optionally the statement
// handle. If no statement handle is given, one is created.
//--------------------------------------------------------------------
public void initialize (
JdbcOdbc odbcApi,
long hdbc,
long hstmt,
Hashtable info,
int resultSetType,
int resultSetConcurrency)
throws SQLException
{
super.initialize (odbcApi, hdbc, hstmt, info,
resultSetType,
resultSetConcurrency);
}
//--------------------------------------------------------------------
// executeQuery
// This method executes a "prepared" query statement.
// See the definition of Statement.executeQuery
//--------------------------------------------------------------------
public ResultSet executeQuery ()
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.executeQuery");
}
ResultSet rs = null;
if (execute ()) {
rs = getResultSet (false);
}
else {
// No ResultSet was produced. Raise an exception
throw new SQLException ("No ResultSet was produced");
}
return rs;
}
//--------------------------------------------------------------------
// executeQuery
// executeQuery with a sql String is invalid for prepared statements
//--------------------------------------------------------------------
public ResultSet executeQuery (
String sql)
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.executeQuery (" + sql + ")");
}
throw new SQLException ("Driver does not support this function",
"IM001");
}
//--------------------------------------------------------------------
// executeUpdate
// This method executes a "prepared" modify statement.
// See the definition of Statement.executeUpdate
//--------------------------------------------------------------------
public int executeUpdate ()
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.executeUpdate");
}
int numRows = -1;
// Execute the statement. If execute returns false, a
// row count exists.
if (!execute ()) {
numRows = getUpdateCount ();
}
else {
// No update count was produced (a ResultSet was). Raise
// an exception
throw new SQLException ("No row count was produced");
}
return numRows;
}
//--------------------------------------------------------------------
// executeUpdate
// executeUpdate with a sql String is invalid for prepared statements
//--------------------------------------------------------------------
public int executeUpdate (
String sql)
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.executeUpdate (" + sql + ")");
}
throw new SQLException ("Driver does not support this function",
"IM001");
}
//--------------------------------------------------------------------
// execute(SQL)
// execute with a sql String is invalid for Prepared statements.
//--------------------------------------------------------------------
public boolean execute (
String sql)
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.execute (" + sql + ")");
}
throw new SQLException ("Driver does not support this function",
"IM001");
}
//--------------------------------------------------------------------
// execute
// This method executed an arbitrary "prepared" statement.
// See the definition of Statement.execute
//--------------------------------------------------------------------
public synchronized boolean execute ()
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.execute");
}
boolean hasResultSet = false;
SQLWarning warning = null;
boolean needData = false;
// Reset warnings
clearWarnings ();
// Reset the statement handle and warning
reset();
// Call SQLExecute
try {
needData = OdbcApi.SQLExecute (hStmt);
// Now loop while more data is needed (i.e. a data-at-
// execution parameter was given). For each parameter
// that needs data, put the data from the input stream.
while (needData)
{
// Get the parameter number that requires data
int paramIndex = OdbcApi.SQLParamData (hStmt);
// If the parameter index is -1, there is no
// more data required
if (paramIndex == -1) {
needData = false;
}
else
{
// Now we have the proper parameter
// index, get the data from the input
// stream and do a SQLPutData
if (batchParamsOn) // is Arrays of Parameters On?.
{
java.io.InputStream x = null;
// Now get current row being processed.
int rowIndex = paramsProcessed[0];
// Now we have the proper parameter and row indexes,
// get the data from the stored input stream array
// and set is as the InputStream of boundParams
// before calling SQLPutData.
x = arrayParams.getInputStreamElement( paramIndex, rowIndex );
boundParams[paramIndex - 1].setInputStream (x, arrayParams.getElementLength( paramIndex, rowIndex ));
}
putParamData (paramIndex);
}//else need data
}//while needdata
}
catch (SQLWarning ex) {
// Save pointer to warning and save with ResultSet
// object once it is created.
warning = ex;
}
// Now loop while more data is needed (i.e. a data-at-
// execution parameter was given). For each parameter
// that needs data, put the data from the input stream.
/****************
while (needData) {
// Get the parameter number that requires data
int paramIndex = OdbcApi.SQLParamData (hStmt);
// If the parameter index is -1, there is no more
// data required
if (paramIndex == -1) {
needData = false;
}
else {
// Now we have the proper parameter index,
// get the data from the input stream
// and do a SQLPutData
putParamData (paramIndex);
}
}
****************/
// Now determine if there is a result set associated with
// the SQL statement that was executed. Get the column
// count, and if it is not zero, there is a result set.
if (getColumnCount () > 0) {
hasResultSet = true;
}
return hasResultSet;
}
// Methods for setting IN parameters into this statement.
// Parameters are numbered starting at 1.
//--------------------------------------------------------------------
// setNull
// You always need to specify a SQL type when sending a NULL.
//--------------------------------------------------------------------
public void setNull (
int parameterIndex,
int sqlType)
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.setNull (" +
parameterIndex + "," + sqlType + ")");
}
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Get the buffer needed for the length
byte lenBuf[] = getLengthBuf (parameterIndex);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
// work around ot keep same precision/scale
// when binding nulls.
int precision = 0;
int scale = 0;
if (sqlType == Types.CHAR || sqlType == Types.VARCHAR)
{
precision = StringDef;
}
else if ( sqlType == Types.NUMERIC || sqlType == Types.DECIMAL )
{
precision = NumberDef;
scale = NumberScale;
}
else if( sqlType == Types.BINARY || sqlType == Types.VARBINARY || sqlType == Types.LONGVARBINARY ) // 4532171
{
sqlType = boundParams[parameterIndex-1].boundType;
precision = binaryPrec;
}
if (precision <= 0)
precision = getPrecision(sqlType);
if (precision <= 0)
precision = 1;
// Bind the parameter to NULL
if (!batchOn)
{
OdbcApi.SQLBindInParameterNull (hStmt, parameterIndex,
sqlType, precision, scale, lenBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].scale=scale;
boundParams[parameterIndex - 1].boundType=sqlType;
boundParams[parameterIndex - 1].boundValue=null;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, null, OdbcDef.SQL_NULL_DATA);
setSqlType(parameterIndex, sqlType);
}
//--------------------------------------------------------------------
// The following methods allow you to set various SQLtypes as
// parameters.
// Note that the method include the SQL type in their name.
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// setBoolean
//--------------------------------------------------------------------
public void setBoolean (
int parameterIndex,
boolean x)
throws SQLException
{
int value = 0;
// If the parameter is true, set the value to 1
if (x) {
value = 1;
}
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Set the parameter as if it were an integer
//setInt (parameterIndex, value);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 4);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterInteger (hStmt, parameterIndex,
Types.BIT, value, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.BIT;
boundParams[parameterIndex - 1].boundValue=new Boolean(x);
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Boolean(x), 0);
setSqlType(parameterIndex, Types.BIT);
}
//--------------------------------------------------------------------
// setByte
//--------------------------------------------------------------------
public void setByte (
int parameterIndex,
byte x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 4);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterInteger (hStmt, parameterIndex,
Types.TINYINT, x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.TINYINT;
boundParams[parameterIndex - 1].boundValue=new Byte(x);
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Byte(x), 0);
setSqlType(parameterIndex, Types.TINYINT);
}
//--------------------------------------------------------------------
// setShort
//--------------------------------------------------------------------
public void setShort (
int parameterIndex,
short x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 4);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterInteger (hStmt, parameterIndex,
Types.SMALLINT, x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.SMALLINT;
boundParams[parameterIndex - 1].boundValue=new Short(x);
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Short(x), 0);
setSqlType(parameterIndex, Types.SMALLINT);
}
//--------------------------------------------------------------------
// setInt
//--------------------------------------------------------------------
public void setInt (
int parameterIndex,
int x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 4);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterInteger (hStmt, parameterIndex,
Types.INTEGER, x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.INTEGER;
boundParams[parameterIndex - 1].boundValue=new Integer(x);
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Integer(x), 0);
setSqlType(parameterIndex, Types.INTEGER);
}
//--------------------------------------------------------------------
// setLong
//--------------------------------------------------------------------
public void setLong (
int parameterIndex,
long x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
//Bug 4495452
// check for ODBC version
// use SQL_C_CHAR for ODBC 2.x and SQL_C_SBIGINT for ODBC 3.x
if (myConnection.getODBCVer () == 2) {
setChar (parameterIndex, Types.BIGINT, (new Long(x)).intValue () , String.valueOf(x) );
}
else if (myConnection.getODBCVer () >= 3) {
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 8);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterBigint (hStmt, parameterIndex,
Types.BIGINT, 0, (long)x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new BigInteger(String.valueOf(x)), 0);
setSqlType(parameterIndex, Types.BIGINT);
}//end if loop checking ODBC version
boundParams[parameterIndex - 1].boundType=Types.BIGINT;
boundParams[parameterIndex - 1].boundValue=new BigInteger(String.valueOf(x));
}
//--------------------------------------------------------------------
// setReal
//--------------------------------------------------------------------
public void setReal (
int parameterIndex,
float x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 8);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterFloat (hStmt, parameterIndex,
Types.REAL, 0, x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Float(x), 0);
setSqlType(parameterIndex, Types.REAL);
}
//--------------------------------------------------------------------
// setFloat
//--------------------------------------------------------------------
public void setFloat (
int parameterIndex,
float x)
throws SQLException
{
// Fix 4532167. setFloat is used for SQL REAL datatype.
setDouble(parameterIndex, (double)x );
}
//--------------------------------------------------------------------
// setDouble
//--------------------------------------------------------------------
public void setDouble (
int parameterIndex,
double x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 8);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterDouble (hStmt, parameterIndex,
Types.DOUBLE, 0, x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.DOUBLE;
boundParams[parameterIndex - 1].boundValue=new Double(x);
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, new Double(x), 0);
setSqlType(parameterIndex, Types.DOUBLE);
}
//--------------------------------------------------------------------
// setBigDecimal
//--------------------------------------------------------------------
public void setBigDecimal (
int parameterIndex,
BigDecimal x)
throws SQLException
{
clearParameter(parameterIndex);
// if x is null, call setNull
if (x == null)
setNull (parameterIndex, Types.NUMERIC);
else
{
// Bind the parameter as a CHAR. We could bind as a
// double, but this may result in a loss of precision
setChar (parameterIndex, Types.NUMERIC, x.scale (), x.toString ());
}
boundParams[parameterIndex - 1].boundType=Types.NUMERIC;
boundParams[parameterIndex-1].boundValue = x;
}
//--------------------------------------------------------------------
// setDecimal
//--------------------------------------------------------------------
public void setDecimal (
int parameterIndex,
BigDecimal x)
throws SQLException
{
clearParameter(parameterIndex);
// if x is null, call setNull
if (x == null)
setNull (parameterIndex, Types.DECIMAL);
else
// Bind the parameter as a CHAR. We could bind as a
// double, but this may result in a loss of precision
setChar (parameterIndex, Types.DECIMAL, x.scale(), x.toString ());
boundParams[parameterIndex - 1].boundType=Types.DECIMAL;
boundParams[parameterIndex-1].boundValue = x;
}
//--------------------------------------------------------------------
// setString
//--------------------------------------------------------------------
public void setString (
int parameterIndex,
String x)
throws SQLException
{
// if x is null, call setNull
if (x == null) {
setNull (parameterIndex, Types.CHAR);
} else if (x.length() >= 254) {
setChar (parameterIndex, Types.LONGVARCHAR, 0, x);
} else {
setChar (parameterIndex, Types.CHAR, 0, x);
}
}
//--------------------------------------------------------------------
// setBytes
//--------------------------------------------------------------------
public void setBytes (
int parameterIndex,
byte x[])
throws SQLException
{
// if x is null, call setNull
if (x == null)
setNull (parameterIndex, Types.BINARY);
else if ( x.length > JdbcOdbcLimits.DEFAULT_IN_PRECISION )
{
setBinaryStream (parameterIndex, new java.io.ByteArrayInputStream(x), x.length);
}
else
{
setBinary (parameterIndex, Types.BINARY, x);
}
boundParams[parameterIndex-1].boundType = Types.BINARY;
boundParams[parameterIndex-1].boundValue = x;
}
//--------------------------------------------------------------------
// setDate
//--------------------------------------------------------------------
public void setDate (
int parameterIndex,
java.sql.Date x)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.DATE);
return;
}
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterDate (hStmt, parameterIndex,
x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.DATE;
boundParams[parameterIndex-1].boundValue = x;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.sql.Date)(x), OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.DATE);
}
//--------------------------------------------------------------------
// setTime
//--------------------------------------------------------------------
public void setTime (
int parameterIndex,
java.sql.Time x)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.TIME);
return;
}
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterTime (hStmt, parameterIndex,
x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.TIME;
boundParams[parameterIndex-1].boundValue = x;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.sql.Time)(x), OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.TIME);
}
//--------------------------------------------------------------------
// setTimestamp
//--------------------------------------------------------------------
public void setTimestamp (
int parameterIndex,
java.sql.Timestamp x)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.TIMESTAMP);
return;
}
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterTimestamp (hStmt, parameterIndex,
x, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundValue=x;
boundParams[parameterIndex - 1].boundType=Types.TIMESTAMP;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.sql.Timestamp)(x), OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.TIMESTAMP);
}
//--------------------------------------------------------------------
// The normal setString and setBytes methods are suitable for passing
// normal sized data. However occasionally it may be necessary to send
// extremely large values as LONGVARCHAR or LONGVARBINARY parameters.
// In this case you can pass in a java.io.InputStream object, and the
// JDBC runtimes will read data from that stream as needed, until they
// reach end-of-file. Note that these stream objects can either be
// standard Java stream objects, or your own subclass that implements
// the standard interface.
// setAsciiStreamParameter and setUnicodeStreamParameter imply the use
// of the SQL LONGVARCHAR type, and setBinaryStreamParameter implies
// the SQL LONGVARBINARY type.
// For each stream type you must specify the number of bytes to be
// read from the stream and sent to the database.
//--------------------------------------------------------------------
public void setAsciiStream (
int ParameterIndex,
java.io.InputStream x,
int length)
throws SQLException
{
setStream (ParameterIndex, x, length, Types.LONGVARCHAR,
JdbcOdbcBoundParam.ASCII);
}
public void setUnicodeStream (
int ParameterIndex,
java.io.InputStream x,
int length)
throws SQLException
{
setStream (ParameterIndex, x, length, Types.LONGVARCHAR,
JdbcOdbcBoundParam.UNICODE);
}
public void setBinaryStream (
int ParameterIndex,
java.io.InputStream x,
int length)
throws SQLException
{
setStream (ParameterIndex, x, length, Types.LONGVARBINARY,
JdbcOdbcBoundParam.BINARY);
binaryPrec = length; // 4532171
}
// Finally, if you need a more dynamic interface, or if you need
// the driver to perform a supported coercion, then you can use
// setObjectParameter.
// You must explicitly specify the SQL type that you want.
// The supported sub-types of Object are java.lang.Boolean,
// java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long,
// java.lang.Float, java.lang.Double, java.lang.String,
// Numeric, java.io.inputStream, byte[],
// java.util.Date, and their subtypes. You can also use a Java null.
//--------------------------------------------------------------------
// clearParameters
// Parameters remain in force for repeated use of the same statement.
// You can use clearParameters to remove any parameters associated with
// a statement.
//--------------------------------------------------------------------
public void clearParameters ()
throws SQLException
{
if (hStmt != OdbcDef.SQL_NULL_HSTMT)
{
OdbcApi.SQLFreeStmt (hStmt, OdbcDef.SQL_RESET_PARAMS);
FreeParams();
for (int pindex=1; boundParams != null &&
pindex <= boundParams.length; pindex++)
{
boundParams[pindex-1].binaryData = null;
boundParams[pindex-1].initialize ();
boundParams[pindex-1].paramInputStream = null;
boundParams[pindex-1].inputParameter = false;
}
}
}
public void clearParameter (int pindex)
throws SQLException
{
if (hStmt != OdbcDef.SQL_NULL_HSTMT)
{
if (boundParams[pindex-1].pA1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pA1, boundParams[pindex-1].pA2);
boundParams[pindex-1].pA1=0;
boundParams[pindex-1].pA2=0;
}
if (boundParams[pindex-1].pB1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pB1, boundParams[pindex-1].pB2);
boundParams[pindex-1].pB1=0;
boundParams[pindex-1].pB2=0;
}
if (boundParams[pindex-1].pC1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pC1, boundParams[pindex-1].pC2);
boundParams[pindex-1].pC1=0;
boundParams[pindex-1].pC2=0;
}
if (boundParams[pindex-1].pS1!=0)
{
OdbcApi.ReleaseStoredChars (boundParams[pindex-1].pS1, boundParams[pindex-1].pS2);
boundParams[pindex-1].pS1=0;
boundParams[pindex-1].pS2=0;
}
boundParams[pindex-1].binaryData = null;
boundParams[pindex-1].initialize ();
boundParams[pindex-1].paramInputStream = null;
boundParams[pindex-1].inputParameter = false;
}
}
//--------------------------------------------------------------------
// setObject
// You can set a parameter as a Java object. See the JDBC spec's
// "Dynamic Programming" chapter for information on valid Java types.
//--------------------------------------------------------------------
public void setObject (
int parameterIndex,
Object x)
throws SQLException
{
setObject (parameterIndex, x, getTypeFromObject (x));
}
public void setObject (
int parameterIndex,
Object x,
int sqlType)
throws SQLException
{
setObject (parameterIndex, x, sqlType, 0);
}
public void setObject (
int parameterIndex,
Object x,
int sqlType,
int scale)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, sqlType);
return;
}
// For each known SQL Type, call the appropriate
// set routine
// bug 4495459
// getting the class name of the input object
String className = null;
if(x instanceof byte[]) {
className = new String("byte[]");
} else {
className = new String(x.getClass().getName());
}
// bug 4495459
// setting the integer and the bigInteger values equivalent to the input boolean value
int bVal = 0;
java.math.BigInteger bi = null;
if(className.equalsIgnoreCase("java.lang.Boolean") ) {
if(x.toString().equalsIgnoreCase("true") ) {
bVal = 1;
bi = java.math.BigInteger.ONE;
} else {
bVal = 0;
bi = java.math.BigInteger.ZERO;
}
}
try {
switch (sqlType) {
// bug 4495459 - start
case Types.CHAR:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.math.BigDecimal")
|| className.equalsIgnoreCase("java.lang.Boolean")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double")
|| className.equalsIgnoreCase("java.sql.Date")
|| className.equalsIgnoreCase("java.sql.Time")
|| className.equalsIgnoreCase("java.sql.Timestamp") ) {
setString (parameterIndex, x.toString());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.VARCHAR:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.math.BigDecimal")
|| className.equalsIgnoreCase("java.lang.Boolean")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double")
|| className.equalsIgnoreCase("java.sql.Date")
|| className.equalsIgnoreCase("java.sql.Time")
|| className.equalsIgnoreCase("java.sql.Timestamp") ) {
setChar (parameterIndex, sqlType, 0, x.toString());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.LONGVARCHAR:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.math.BigDecimal")
|| className.equalsIgnoreCase("java.lang.Boolean")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double")
|| className.equalsIgnoreCase("java.sql.Date")
|| className.equalsIgnoreCase("java.sql.Time")
|| className.equalsIgnoreCase("java.sql.Timestamp") ) {
setChar (parameterIndex, sqlType, 0, x.toString());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.NUMERIC:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Short")) {
BigDecimal bd1 = new BigDecimal(new java.math.BigInteger(x.toString()), 0);
BigDecimal bd2 = bd1.movePointRight(scale);
BigDecimal bd3 = bd2.movePointLeft(scale);
setBigDecimal(parameterIndex, bd3);
} else if(className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double")
|| className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setBigDecimal(parameterIndex, new BigDecimal(x.toString()));
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setBigDecimal(parameterIndex, new BigDecimal(bi.toString()));
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.DECIMAL:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Short")) {
BigDecimal bd1 = new BigDecimal(new java.math.BigInteger(x.toString()), 0);
BigDecimal bd2 = bd1.movePointRight(scale);
BigDecimal bd3 = bd2.movePointLeft(scale);
setDecimal(parameterIndex, bd3);
} else if(className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double")
|| className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setDecimal(parameterIndex, new BigDecimal(x.toString()));
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setDecimal(parameterIndex, new BigDecimal(bi.toString()));
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.BIT:
/*
the string representation of the boolean value true is "true";
every other string is equivalent to the boolean value "false"
*/
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Boolean") ) {
if(x.toString().equalsIgnoreCase("true") ) {
setBoolean(parameterIndex, true);
} else {
setBoolean(parameterIndex, false);
}
} else if(className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
if(x.toString().equalsIgnoreCase("1") ) {
setBoolean(parameterIndex, true);
} else {
setBoolean(parameterIndex, false);
}
} else if(className.equalsIgnoreCase("java.lang.Float") ) {
if((new Float(0)).compareTo(x) == 0) {
setBoolean(parameterIndex, false);
} else {
setBoolean(parameterIndex, true);
}
} else if(className.equalsIgnoreCase("java.lang.Double") ) {
if((new Double(0)).compareTo(x) == 0) {
setBoolean(parameterIndex, false);
} else {
setBoolean(parameterIndex, true);
}
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.TINYINT:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Float") ) {
setByte(parameterIndex, (new Float(x.toString())).byteValue());
} else if(className.equalsIgnoreCase("java.lang.Double") ) {
setByte(parameterIndex, (new Double(x.toString())).byteValue());
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setByte(parameterIndex, (byte)bVal);
} else if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setByte (parameterIndex, (new Byte(x.toString())).byteValue());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.SMALLINT:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Float") ) {
setShort(parameterIndex, (new Float(x.toString())).shortValue());
} else if(className.equalsIgnoreCase("java.lang.Double") ) {
setShort(parameterIndex, (new Double(x.toString())).shortValue());
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setShort(parameterIndex, (short)bVal);
} else if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setShort (parameterIndex, (new Short(x.toString())).shortValue ());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.INTEGER:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Float") ) {
setInt(parameterIndex, (new Float(x.toString())).intValue());
} else if(className.equalsIgnoreCase("java.lang.Double") ) {
setInt(parameterIndex, (new Double(x.toString())).intValue());
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setInt(parameterIndex, bVal);
} else if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setInt (parameterIndex, (new Integer(x.toString())).intValue ());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.BIGINT:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Float") ) {
setLong(parameterIndex, (new Float(x.toString())).longValue());
} else if(className.equalsIgnoreCase("java.lang.Double") ) {
setLong(parameterIndex, (new Double(x.toString())).longValue());
} else if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setLong(parameterIndex, (long)bVal);
} else if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.math.BigDecimal") ) {
setLong (parameterIndex, (new Long(x.toString())).longValue ());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.REAL:
case Types.FLOAT:
case Types.DOUBLE:
//4744654; adding short
if(className.equalsIgnoreCase("java.lang.Boolean") ) {
setDouble(parameterIndex, (double)bVal);
} else if(className.equalsIgnoreCase("java.lang.String")
|| className.equalsIgnoreCase("java.lang.Integer")
|| className.equalsIgnoreCase("java.lang.Short")
|| className.equalsIgnoreCase("java.lang.Long")
|| className.equalsIgnoreCase("java.math.BigDecimal")
|| className.equalsIgnoreCase("java.lang.Float")
|| className.equalsIgnoreCase("java.lang.Double") ) {
setDouble (parameterIndex, (new Double(x.toString())).doubleValue ());
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.BINARY:
if(className.equalsIgnoreCase("java.lang.String") ) {
setBytes(parameterIndex, ((String)x).getBytes());
} else if(className.equalsIgnoreCase("byte[]") ) {
setBytes (parameterIndex, (byte[]) x);
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.VARBINARY:
case Types.LONGVARBINARY:
byte[] y = null;
if(className.equalsIgnoreCase("java.lang.String") ) {
y = ((String)x).getBytes();
} else if(className.equalsIgnoreCase("byte[]") ) {
y = (byte[]) x;
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
if ( y.length > JdbcOdbcLimits.DEFAULT_IN_PRECISION ) {
setBinaryStream (parameterIndex, new java.io.ByteArrayInputStream(y), y.length);
} else {
setBinary (parameterIndex, sqlType, y);
}
break;
case Types.DATE:
if(className.equalsIgnoreCase("java.lang.String") ) {
setDate(parameterIndex, java.sql.Date.valueOf(x.toString()));
} else if(className.equalsIgnoreCase("java.sql.Timestamp") ) {
setDate(parameterIndex, new java.sql.Date(java.sql.Timestamp.valueOf(x.toString()).getTime()));
} else if(className.equalsIgnoreCase("java.sql.Date") ) {
setDate (parameterIndex, (java.sql.Date) x);
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.TIME:
if(className.equalsIgnoreCase("java.lang.String") ) {
setTime(parameterIndex, java.sql.Time.valueOf(x.toString()));
} else if(className.equalsIgnoreCase("java.sql.Timestamp") ) {
setTime(parameterIndex, new java.sql.Time(java.sql.Timestamp.valueOf(x.toString()).getTime()));
} else if(className.equalsIgnoreCase("java.sql.Time") ) {
setTime (parameterIndex, (java.sql.Time) x);
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
case Types.TIMESTAMP:
if(className.equalsIgnoreCase("java.lang.String") ) {
setTimestamp(parameterIndex, java.sql.Timestamp.valueOf(x.toString()));
} else if(className.equalsIgnoreCase("java.sql.Date") ) {
setTimestamp(parameterIndex, new java.sql.Timestamp(java.sql.Date.valueOf(x.toString()).getTime()));
} else if(className.equalsIgnoreCase("java.sql.Timestamp") ) {
setTimestamp (parameterIndex, (java.sql.Timestamp) x);
} else {
throw new SQLException("Conversion not supported by setObject!!");
}
break;
// bug 4495459 - end
default:
throw new SQLException ("Unknown SQL Type for PreparedStatement.setObject (SQL Type=" + sqlType);
}
} catch(SQLException sqle) {
throw new SQLException("SQL Exception : " + sqle.getMessage());
}
catch (Exception e) {
throw new SQLException("Unexpected exception : " + e.getMessage());
}
}
// New JDBC 2.0 API
//--------------------------------------------------------------------
// addBatch(SQL)
// addBatch with a sql String is invalid for Prepared statements.
//--------------------------------------------------------------------
public void addBatch (
String sql)
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.addBatch (" + sql + ")");
}
throw new SQLException ("Driver does not support this function",
"IM001");
}
//--------------------------------------------------------------------
// clearBatch()
// clears the parameter list for PreparedStatements.
//--------------------------------------------------------------------
public void clearBatch ()
{
if (OdbcApi.getTracer().isTracing ())
{
OdbcApi.getTracer().trace ("*PreparedStatement.clearBatch");
}
try
{
if ( batchSqlVec != null )
{
cleanUpBatch();
batchOn = false;
batchParamsOn = false;
}
//arrayParams.clearParameterSet();
}
catch (Exception e)
{
e.printStackTrace();
}
}
//--------------------------------------------------------------------
// addBatch()
// adds a set Of Parameters for executeBatch Updates.
//--------------------------------------------------------------------
public void addBatch() throws SQLException
{
if (OdbcApi.getTracer().isTracing ()){
OdbcApi.getTracer().trace ("*PreparedStatement.addBatch");
}
try
{
int storedSize;
//get from storage Vector and add values to it.
batchSqlVec = myConnection.getBatchVector(this);
// If adding parameter for the first time
// create the vector to hold them.
if ( batchSqlVec == null )
{
batchSqlVec = new Vector(5,10);
storedSize = 0;
}
else
{
storedSize = batchSqlVec.size();
}
Object[] addBatchParams = arrayParams.getStoredParameterSet();
int[] addBatchParamsIdx = arrayParams.getStoredIndexSet();
int batchDataLen = addBatchParams.length;
int batchIdxLen = addBatchParamsIdx.length;
if ( batchIdxLen == numParams )
{
batchSqlVec.addElement(addBatchParams);
myConnection.setBatchVector(batchSqlVec, this);
arrayParams.storeRowIndex( storedSize, addBatchParamsIdx );
batchOn = true;
}
else if ( storedSize == 0 )
{
throw new SQLException("Parameter-Set has missing values.");
}
else
{
//myConnection.setBatchVector(batchSqlVec, this);
batchOn = true;
}
}
catch (NullPointerException e)
{
//throw new SQLException("Parameter Set has missing values");
batchOn = false;
}
}
//--------------------------------------------------------------------
// executeBatchUpdate()
// performs execution for Statement.executeBatch().
//--------------------------------------------------------------------
public int[] executeBatchUpdate()
throws BatchUpdateException
{
int[] updateCount = {};
if (numParams <= 0)
{
// Reset normal Bind.
batchSize = 0;
batchOn = false;
batchParamsOn = false;
return executeNoParametersBatch();
}
batchSqlVec = myConnection.getBatchVector(this);
if ( batchSqlVec != null )
{
batchSize = batchSqlVec.size();
}
else
{
//throw new BatchUpdateException("Nothing to execute", updateCount);
updateCount = new int[0];
return updateCount;
}
if (batchSize > 0)
{
updateCount = new int[batchSize];
// 4486684 - Deallocate the previous arrays and the global refs before reallocating them.
FreeIntParams();
// initialize process and status pointers.
paramStatusArray = new int[batchSize];
paramsProcessed = new int[batchSize];
boolean emulateBatch = true;
int paramReset = 0;
try
{
if (!emulateBatch) {
// Even if Batch SQL support is false,
// SetStmtAttr can be call to try and set
// SQL_ATTR_PARAMSET_SIZE > 1 for arrays of parameters.
// Otherwise, executeBatch must be emulated.
OdbcApi.SQLSetStmtAttr (hStmt,
OdbcDef.SQL_ATTR_PARAM_BIND_TYPE,
OdbcDef.SQL_PARAM_BIND_BY_COLUMN, 0);
// If one can set this attribute,
// then one can bind arrays of parameters.
// otherwise, emulate batch.
try
{
setStmtParameterSize(batchSize);
paramReset = getStmtParameterAttr(OdbcDef.SQL_ATTR_PARAMSET_SIZE);
}
catch (SQLException e)
{
batchSupport = false;
}
}
if (paramReset != batchSize)
{
batchSupport = false;
try
{
setStmtParameterSize(1);
}
catch (SQLException e)
{
//ignore exception -- e.printStackTrace();
}
}
else
{
//4486684
pA2 = new long[2];
pA2[0] = 0;
pA2[1] = 0;
OdbcApi.SQLSetStmtAttrPtr (hStmt,
OdbcDef.SQL_ATTR_PARAM_STATUS_PTR,
paramStatusArray, 0, pA2);
//4486684
pA1 = new long[2];
pA1[0] = 0;
pA1[1] = 0;
OdbcApi.SQLSetStmtAttrPtr (hStmt,
OdbcDef.SQL_ATTR_PARAMS_PROCESSED_PTR,
paramsProcessed, 0, pA1);
batchSupport = true;
}
}
catch (SQLException e)
{
batchSupport = false;
}
if ( batchSupport == true )
{
batchParamsOn = true;
int exceptionCount[] = {};
// generate 2D storage values and index arrays
arrayParams.builtColumWiseParameteSets( batchSize, batchSqlVec );
for (int i = 0; i < numParams; i++)
{
// re-initialize Bind parameters
arrayDef = 0;
arrayScale = 0;
int sqlType = 0;
int parameterIndex = i + 1;
try
{
Object[] paramCol = arrayParams.getColumnWiseParamSet(parameterIndex);
int[] indArrs = arrayParams.getColumnWiseIndexArray(parameterIndex);
// Dedefines the Column's specific precision and scale.
// by setting the Global arrayDef and arrayScale.
setPrecisionScaleArgs(paramCol, indArrs);
sqlType = getSqlType(parameterIndex);
// Binds the Object array
// with conversion to the
// specified SQLType.
bindArrayOfParameters(parameterIndex, sqlType,
arrayDef, arrayScale,
paramCol, indArrs);
}
catch (SQLException e)
{
e.printStackTrace();
}
}
// status and count of individual updates not yet available.
try
{
if (!execute())
{
paramStatusArray[0] = getUpdateCount();
arrayParams.clearStoredRowIndexs(); // must debug for testcases.
updateCount = paramStatusArray;
// Reset normal Bind.
batchOn = false;
batchParamsOn = false;
cleanUpBatch();
}
else
{
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException("SQL Attempt to produce a ResultSet from executeBatch", paramStatusArray);
}
}
catch (SQLException e)
{
try
{
paramStatusArray[0] = getUpdateCount();
}catch(SQLException uCe){}
// get the last successful row #.
exceptionCount = new int[paramsProcessed[0] - 1];
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException(e.getMessage(), e.getSQLState(), exceptionCount);
}
} // end of batch support.
else if ( batchSupport == false )
{
// Reset normal Bind.
// and try to emulate batch support.
batchOn = false;
batchParamsOn = false;
return emulateExecuteBatch();
}
}
return updateCount;
}
//--------------------------------------------------------------------
// executeNoParametersBatch()
// executes on calls to executeBatch() for Statements w/o Parameters
//--------------------------------------------------------------------
protected int[] executeNoParametersBatch()
throws BatchUpdateException
{
int[] singleUpdate = new int[1];
try
{
if (!execute())
{
cleanUpBatch();
singleUpdate[0] = getUpdateCount();
}
else
{
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException("SQL Attempt to produce a ResultSet from executeBatch", singleUpdate);
}
}
catch (SQLException e)
{
try
{
singleUpdate[0] = getUpdateCount();
}catch(SQLException uCe){}
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException(e.getMessage(), e.getSQLState(), singleUpdate);
}
return singleUpdate;
}
//--------------------------------------------------------------------
// setStmtParameterSize
// gets the array-size for column wise binding
//--------------------------------------------------------------------
protected int getStmtParameterAttr(int option)
throws SQLException
{
try
{
clearWarnings ();
return OdbcApi.SQLGetStmtAttr (hStmt, option);
}
catch (SQLException e)
{
e.printStackTrace();
return -1;
}
}
//--------------------------------------------------------------------
// setStmtParameterSize
// sets the array-size for column wise binding
//--------------------------------------------------------------------
protected void setStmtParameterSize(int size)
throws SQLException
{
try
{
clearWarnings ();
OdbcApi.SQLSetStmtAttr (hStmt, OdbcDef.SQL_ATTR_PARAMSET_SIZE, size, 0);
}
catch (SQLException e)
{
e.printStackTrace();
}
}
//--------------------------------------------------------------------
// bindArrayOfParameters
// binds Object Array with indicated SQLType.
//--------------------------------------------------------------------
protected void bindArrayOfParameters(
int parameterIndex,
int sqlType,
int arrayDef,
int arrayScale,
Object[] paramCol,
int[] indArrs)
throws SQLException
{
switch (sqlType)
{
case Types.CHAR:
case Types.VARCHAR:
case Types.NUMERIC:
case Types.DECIMAL:
OdbcApi.SQLBindInParameterStringArray (
hStmt, parameterIndex,
sqlType, paramCol, arrayDef,
arrayScale, indArrs);
break;
case Types.LONGVARCHAR:
// check if the Array contain Stream Data.
if ( (getTypeFromObjectArray (paramCol) == Types.LONGVARBINARY) )
{
arrayParams.setInputStreamElements(parameterIndex, paramCol);
OdbcApi.SQLBindInParameterAtExecArray (
hStmt, parameterIndex,
sqlType, arrayDef, indArrs);
break;
}
else
{
OdbcApi.SQLBindInParameterStringArray (
hStmt, parameterIndex,
sqlType, paramCol, arrayDef,
arrayScale, indArrs);
break;
}
case Types.BIT:
case Types.TINYINT:
case Types.SMALLINT:
case Types.INTEGER:
OdbcApi.SQLBindInParameterIntegerArray (
hStmt,
parameterIndex,
sqlType,
paramCol,
indArrs);
break;
case Types.DOUBLE:
OdbcApi.SQLBindInParameterDoubleArray (
hStmt,
parameterIndex,
sqlType,
paramCol,
indArrs);
break;
case Types.BIGINT:
case Types.FLOAT:
case Types.REAL:
OdbcApi.SQLBindInParameterFloatArray (
hStmt,
parameterIndex,
sqlType,
paramCol,
indArrs);
break;
case Types.DATE:
OdbcApi.SQLBindInParameterDateArray (
hStmt,
parameterIndex,
paramCol,
indArrs);
break;
case Types.TIME:
OdbcApi.SQLBindInParameterTimeArray (
hStmt,
parameterIndex,
paramCol,
indArrs);
break;
case Types.TIMESTAMP:
OdbcApi.SQLBindInParameterTimestampArray (
hStmt,
parameterIndex,
paramCol,
indArrs);
break;
case Types.BINARY:
case Types.VARBINARY:
OdbcApi.SQLBindInParameterBinaryArray (
hStmt,
parameterIndex,
sqlType, paramCol,
arrayDef, indArrs);
break;
case Types.LONGVARBINARY:
arrayParams.setInputStreamElements(parameterIndex, paramCol);
OdbcApi.SQLBindInParameterAtExecArray (
hStmt, parameterIndex,
sqlType, arrayDef, indArrs);
break;
}//end of Bind Array!
}
//--------------------------------------------------------------------
// emulateExecuteBatch.
// executes stored list of updates one by one.
//--------------------------------------------------------------------
protected int[] emulateExecuteBatch()
throws BatchUpdateException
{
int[] emulateCount = new int[batchSize];
int exceptionCount[] = {};
int successCount = 0;
for (int i = 0; i < batchSize; i++)
{
// Gets the next record as an Object array!
// and get the record's length indicator array!
Object[] params = (Object[]) batchSqlVec.elementAt(i);
int[] paramIndicator = arrayParams.getStoredRowIndex( i );
try
{
for (int j = 0 ; j < params.length; j++)
{
int validateType = Types.OTHER;
int streamLen = 0;
int streamType = 0;
int parameterIndex = j + 1;
java.io.InputStream x = null;
validateType = getTypeFromObject (params[j]);
int storeType = getSqlType(parameterIndex);
// check if we have BINARY streams.
// for the following Data Types.
if ( validateType == Types.LONGVARBINARY )
{
x = (java.io.InputStream)params[j];
streamLen = paramIndicator[j];
switch(storeType)
{
case Types.LONGVARBINARY:
streamType = JdbcOdbcBoundParam.BINARY;
break;
case Types.LONGVARCHAR:
streamType = boundParams[j].getStreamType ();
break;
}
}
// Determine if the object is an InputStream
// and bind it with setStream. If not, use setObject.
if ( (streamLen > 0) && (0 < streamType ) )
{
switch(streamType)
{
case JdbcOdbcBoundParam.ASCII:
case JdbcOdbcBoundParam.UNICODE:
setStream (parameterIndex, x, streamLen,
Types.LONGVARCHAR, streamType);
break;
case JdbcOdbcBoundParam.BINARY:
setStream (parameterIndex, x, streamLen,
Types.LONGVARBINARY, streamType);
break;
}//end bind switch;
}
else
{
if(validateType != Types.OTHER)
{
if (validateType != Types.NULL)
{
setObject(parameterIndex , params[j], storeType);
}
else
{
setNull(parameterIndex, storeType);
}
}
}
}//end internal for loop.
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
if (!execute ())
{
myConnection.removeBatchVector(this);
emulateCount[i] = getUpdateCount ();
successCount++;
// May be requiered for Drivers that reuse modified
// BindParameter values from the first execute.
//if (hStmt != OdbcDef.SQL_NULL_HSTMT)
//{
//System.out.println("reset parameters Prepared free stmt = " + hStmt);
// OdbcApi.SQLFreeStmt (hStmt, OdbcDef.SQL_RESET_PARAMS);
//}
}
else
{
for (int j = 0; j < i - 1; j++)
{
exceptionCount = new int[successCount];
exceptionCount[j] = emulateCount[j];
}
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException("SQL Attempt to produce a ResultSet from executeBatch", exceptionCount);
}
}
catch(SQLException e)
{
for (int j = 0; j < i - 1; j++)
{
exceptionCount = new int[successCount];
exceptionCount[j] = emulateCount[j];
}
cleanUpBatch();
throw new JdbcOdbcBatchUpdateException(e.getMessage(), e.getSQLState(), exceptionCount);
}
}//end for loop.
cleanUpBatch();
return emulateCount;
}
//--------------------------------------------------------------------
// cleanUpBatch()
// after executeBatch is complete, or if an Exception is thrown:
// performs clean-up by removing the Batch List from the Connection
// parent, and resets storage of Parameters Vector and BatchSize to 0.
//--------------------------------------------------------------------
protected void cleanUpBatch()
{
myConnection.removeBatchVector(this);
if (batchSqlVec != null)
{
batchSqlVec.setSize(0);
batchSize = 0;
}
}
//--------------------------------------------------------------------
// setPrecisionScaleArgs()
// for array of parameters during executeBatch:
// check if the SQL Type to perform precision and scale calculations.
//--------------------------------------------------------------------
protected void setPrecisionScaleArgs(Object[] parmset, int[] lengthInd)
{
int colSetType = getTypeFromObjectArray (parmset);
for (int i = 0; i < batchSize; i++)
{
byte[] objByte = null;
String objStr = null;
BigDecimal decVal = null;
int setDef = 0;
try
{
if ( (colSetType == Types.DECIMAL) ||
(colSetType == Types.NUMERIC) )
{
if (parmset[i] != null)
{
int setScale = 0;
decVal = (BigDecimal)parmset[i];
objStr = (decVal).toString();
setDef = objStr.indexOf('.');
if (setDef == -1)
{
setDef = objStr.length();
}
else
{
setScale = (decVal).scale();
setDef += setScale + 1;
}
//if (objStr.startsWith("-"))
//{
//setDef--;
//}
if ( setScale > arrayScale)
{
arrayScale = setScale;
}
}
}
else if ( (colSetType == Types.CHAR) ||
(colSetType == Types.VARCHAR) )
{
if (parmset[i] != null)
{
objStr = ((String)parmset[i]);
setDef = objStr.length();
}
}
else if ( colSetType == Types.LONGVARBINARY )
{
if ( lengthInd[i] > arrayDef)
{
arrayDef = lengthInd[i];
}
}
else if ( (colSetType == Types.BINARY) ||
(colSetType == Types.VARBINARY) )
{
if (parmset[i] != null)
{
objByte = (byte[])parmset[i];
setDef = objByte.length;
}
}
// Use the Largest length as the columns precision!
if ( setDef > arrayDef)
{
arrayDef = setDef;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}// end of for loop!
}
// MOVED FROM CALLABLE STATEMENT
//--------------------------------------------------------------------
// setSqlType
// Sets the Java sql type for when registering an OUT parameter
//--------------------------------------------------------------------
protected void setSqlType (
int index,
int type)
{
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
boundParams[index - 1].setSqlType (type);
}
}
// MOVED FROM CALLABLE STATEMENT
//--------------------------------------------------------------------
// getSqlType
// Gets the Java sql type for when registering an OUT parameter
//--------------------------------------------------------------------
protected int getSqlType (
int index)
{
int type = Types.OTHER;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
type = boundParams[index - 1].getSqlType ();
}
return type;
}
public void setCharacterStream (
int parameterIndex,
Reader reader,
int length)
throws SQLException
{
clearParameter(parameterIndex);
//throw new UnsupportedOperationException();
// Set of Streams to read chars from:
java.io.BufferedReader bReader = null;
java.io.BufferedOutputStream bout = null;
// Set of Streams to write Bytes to:
java.io.ByteArrayOutputStream outBytes = null;
java.io.ByteArrayInputStream inAsBytes = null;
// Get the connection's character Set.
String encoding = OdbcApi.charSet;
// set character buffer size.
int bufLength = JdbcOdbcLimits.DEFAULT_BUFFER_LENGTH;
if (length < bufLength)
bufLength = length;
int inputLength = 0;
try
{
if (reader != null)
{
int totCount = 0;
int count = 0;
bReader = new java.io.BufferedReader(reader);
outBytes = new java.io.ByteArrayOutputStream();
bout = new java.io.BufferedOutputStream(outBytes);
char[] charBuffer = new char[bufLength];
while ( count != -1 )
{
byte[] bytesBuffer = new byte[0];
count = bReader.read(charBuffer);
if (count != -1)
{
// re-size the char buffer to
// prevent conversion of unnessesary
// chars.
char[] tmpCharBuf = new char[count];
for (int i = 0; i < count; i++)
{
tmpCharBuf[i] = charBuffer[i];
}
//totCount += count;
//System.out.println("Chars read = " + count);
//System.out.println("total chars read = " + totCount);
// calculate the length of bytes to write to the outputstream.
// For ASCII, A one to one will do. However double or even triple
// byte characters will require for the stream to write more bytes.
// out of the bytes buffer.
bytesBuffer = CharsToBytes (encoding, tmpCharBuf);
// Strip off the null terminator byte.
int byteCount = bytesBuffer.length - 1;
// write bytes to the outputStream
bout.write(bytesBuffer, 0, byteCount);
// flush any unwriten bytes
bout.flush();
} //end if.
} //end while.
// set the InputStream length.
inputLength = outBytes.size();
// debug prior to sending into the database.
// System.out.println("Input length = " + inputLength);
// System.out.println("Input value = " + outBytes.toString());
inAsBytes = new java.io.ByteArrayInputStream(outBytes.toByteArray());
}
}
catch (java.io.IOException ioe)
{
throw new SQLException("CharsToBytes Reader Conversion: " + ioe.getMessage());
}
// process Reader as an InputStream.
//Bug Fix 4494735
//VARCHAR has been replaced by LONGVARCHAR
setStream (parameterIndex, inAsBytes, inputLength, Types.LONGVARCHAR,
JdbcOdbcBoundParam.BINARY);
}
public void setRef (
int i,
Ref x)
throws SQLException
{
throw new UnsupportedOperationException();
}
public void setBlob (
int i,
Blob x)
throws SQLException
{
throw new UnsupportedOperationException();
}
public void setClob (
int i,
Clob x)
throws SQLException
{
throw new UnsupportedOperationException();
}
public void setArray (
int i,
Array x)
throws SQLException
{
throw new UnsupportedOperationException();
}
public ResultSetMetaData getMetaData ()
throws SQLException
{
if (OdbcApi.getTracer().isTracing()) {
OdbcApi.getTracer().trace ("*PreparedStatement.getMetaData");
}
JdbcOdbcResultSet rs = null;
// If the Statement set has been closed, throw an exception
if (hStmt == OdbcDef.SQL_NULL_HSTMT) {
throw new SQLException("Statement is closed");
}
// Now, create a new ResultSet object, and initialize it
rs = new JdbcOdbcResultSet ();
rs.initialize (OdbcApi, hDbc, hStmt, true, null);
return new JdbcOdbcResultSetMetaData (OdbcApi, rs);
}
//--------------------------------------------------------------------
// setDate w/ Calendar
// Sets the designated parameter to a java.sql.Date value,
// using the given Calendar object.
//--------------------------------------------------------------------
public void setDate (
int parameterIndex,
Date x,
Calendar cal)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.DATE);
return;
}
// Fix 4380653. Convert to GMT before sending to database.
// Take a fresh Calendar Instance, since we have already done
// the adjustment.
long millis = utils.convertToGMT(x,cal);
x = new Date(millis);
cal = Calendar.getInstance();
//package the Date value into the Calendar Object.
cal.setTime(x);
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterCalendarDate (hStmt, parameterIndex,
cal, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.DATE;
boundParams[parameterIndex-1].boundValue = x;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.util.Calendar)cal, OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.DATE);
}
//--------------------------------------------------------------------
// setTime w/ Calendar
// Sets the designated parameter to a java.sql.Time value,
// using the given Calendar object.
//--------------------------------------------------------------------
public void setTime (
int parameterIndex,
Time x,
Calendar cal)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.TIME);
return;
}
// Fix 4380653. Convert to GMT before sending to database.
// Take a fresh Calendar Instance, since we have already done
// the adjustment.
long millis = utils.convertToGMT(x,cal);
x = new Time(millis);
cal = Calendar.getInstance();
//package Time into the Calendar Object.
cal.setTime(x);
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterCalendarTime (hStmt, parameterIndex,
cal, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.TIME;
boundParams[parameterIndex-1].boundValue = x;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.util.Calendar)cal, OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.TIME);
}
//--------------------------------------------------------------------
// setTimestamp w/ Calendar
// Sets the designated parameter to a java.sql.Timestamp value,
// using the given Calendar object.
//--------------------------------------------------------------------
public void setTimestamp (
int parameterIndex,
Timestamp x,
Calendar cal)
throws SQLException
{
// if x is null, call setNull
if (x == null)
{
setNull (parameterIndex, Types.TIMESTAMP);
return;
}
// Fix 4380653. Convert to GMT before sending to database.
// Take a fresh Calendar Instance, since we have already done
// the adjustment.
long millis = utils.convertToGMT(x,cal);
x = new Timestamp(millis);
cal = Calendar.getInstance();
//package Timestamp into the Calendar Object.
cal.setTime(x);
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex, 32);
long buffers[]=new long[2];
buffers[0]=0;
buffers[1]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterCalendarTimestamp (hStmt, parameterIndex,
cal, bindBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].boundType=Types.TIMESTAMP;
boundParams[parameterIndex-1].boundValue = x;
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (java.util.Calendar)cal, OdbcDef.SQL_NTS);
setSqlType(parameterIndex, Types.TIMESTAMP);
}
public void setNull (
int paramIndex,
int sqlType,
String typeName)
throws SQLException
{
throw new UnsupportedOperationException();
}
//--------------------------------------------------------------------
// initBoundParam
// Initialize the bound parameter objects
//--------------------------------------------------------------------
public void initBoundParam ()
throws SQLException
{
// Get the number of parameters
numParams = OdbcApi.SQLNumParams (hStmt);
// There are parameter markers, allocate the bound
// parameter objects
if (numParams > 0) {
// Allocate an array of bound parameter objects
boundParams = new JdbcOdbcBoundParam[numParams];
// Allocate and initialize each bound parameter
for (int i = 0; i < numParams; i++) {
boundParams[i] = new JdbcOdbcBoundParam ();
boundParams[i].initialize ();
}
// Allocate an Array storage/manipulator
// for Batch Update bound parameter objects.
arrayParams = new JdbcOdbcBoundArrayOfParams( numParams );
// If SQL_PARC_BATCH supported,
// signals that Row Counts will be returned
// for individual statements.
// Else, Batch Update is not supported and
// expected to emulate Batch.
batchRCFlag = myConnection.getBatchRowCountFlag(1);
// double check if row counts are returned.
if ( (batchRCFlag > 0) && (batchRCFlag == OdbcDef.SQL_PARC_BATCH) )
{
batchSupport = true;
}
else
{
batchSupport = false;
}
StringDef = 0;
NumberDef = 0;
NumberDef = 0;
binaryPrec = 0; // 4532171
}
}
//====================================================================
// Protected methods
//====================================================================
//--------------------------------------------------------------------
// allocBindBuf
// Allocate storage for the permanent data buffer for the bound
// parameter.
//--------------------------------------------------------------------
protected byte[] allocBindBuf (
int index,
int bufLen)
{
byte b[] = null;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
b = boundParams[index - 1].allocBindDataBuffer (
bufLen);
}
return b;
}
//--------------------------------------------------------------------
// getDataBuf
// Gets the data buffer for the given parameter index
//--------------------------------------------------------------------
protected byte[] getDataBuf (
int index)
{
byte b[] = null;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
b = boundParams[index - 1].getBindDataBuffer ();
}
return b;
}
//--------------------------------------------------------------------
// getLengthBuf
// Gets the length buffer for the given parameter index
//--------------------------------------------------------------------
protected byte[] getLengthBuf (
int index)
{
byte b[] = null;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
b = boundParams[index - 1].getBindLengthBuffer ();
}
return b;
}
//--------------------------------------------------------------------
// getParamLength
// Returns the length of the given parameter number. When each
// parameter was bound, a 4-byte buffer was given to hold the
// length (stored in native format). Get the buffer, convert the
// buffer from native format, and return it. If the length is -1,
// the column is considered to be NULL.
//--------------------------------------------------------------------
public int getParamLength (
int index)
{
int paramLen = OdbcDef.SQL_NULL_DATA;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
// Now get the length of the parameter from the
// bound param array. -1 is returned if it is null.
paramLen = OdbcApi.bufferToInt (
boundParams[index - 1].getBindLengthBuffer ());
}
return paramLen;
}
//--------------------------------------------------------------------
// putParamData
// Puts parameter data from a previously bound input stream. The
// input stream was bound using SQL_LEN_DATA_AT_EXEC.
//--------------------------------------------------------------------
protected void putParamData (
int index)
throws SQLException, JdbcOdbcSQLWarning
{
// We'll transfer up to maxLen at a time
int maxLen = JdbcOdbcLimits.MAX_PUT_DATA_LENGTH;
int bufLen;
int realLen;
byte buf[] = new byte[maxLen];
boolean endOfStream = false;
// Sanity check the parameter index
if ((index < 1) ||
(index > numParams)) {
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("Invalid index for putParamData()");
}
return;
}
// Get the information about the input stream
java.io.InputStream inputStream =
boundParams[index - 1].getInputStream ();
int inputStreamLen = boundParams[index - 1].getInputStreamLen ();
int inputStreamType = boundParams[index - 1].getStreamType ();
// Loop while more data from the input stream
while (!endOfStream) {
// Read some data from the input stream
try {
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("Reading from input stream");
}
bufLen = inputStream.read (buf);
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("Bytes read: " + bufLen);
}
}
catch (java.io.IOException ex) {
// If an I/O exception was generated, turn
// it into a SQLException
throw new SQLException (ex.getMessage ());
}
// -1 as the number of bytes read indicates that
// there is no more data in the input stream
if (bufLen == -1) {
// Sanity check to ensure that all the data we said we
// had was read. If not, raise an exception
if (inputStreamLen != 0) {
throw new SQLException ("End of InputStream reached before satisfying length specified when InputStream was set");
}
endOfStream = true;
break;
}
// If we got more bytes than necessary, truncate
// the buffer by re-setting the buffer length. Also,
// indicate that we don't need to read any more.
if (bufLen > inputStreamLen) {
bufLen = inputStreamLen;
endOfStream = true;
}
realLen = bufLen;
// For UNICODE streams, strip off the high byte and set the
// number of actual bytes present. It is assumed that
// there are 2 bytes present for every UNICODE character - if
// not, then that's not our problem
if (inputStreamType == JdbcOdbcBoundParam.UNICODE) {
realLen = bufLen / 2;
for (int ii = 0; ii < realLen; ii++) {
buf[ii] = buf[(ii * 2) + 1];
}
}
// Put the data
OdbcApi.SQLPutData (hStmt, buf, realLen);
// Decrement the number of bytes still needed
inputStreamLen -= bufLen;
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("" + inputStreamLen + " bytes remaining");
}
// If there is no more data to be read, exit loop
if (inputStreamLen == 0) {
endOfStream = true;
}
}
}
//--------------------------------------------------------------------
// setStream
// Sets an input stream as a parameter, using the given SQL type
//--------------------------------------------------------------------
public void setStream (
int ParameterIndex,
java.io.InputStream x,
int length,
int SQLtype,
int streamType)
throws SQLException
{
clearParameter(ParameterIndex);
// Indicate that this is an input parameter
setInputParameter (ParameterIndex, true);
// Get the buffer needed for the length
byte lenBuf[] = getLengthBuf (ParameterIndex);
// Allocate a new buffer for the parameter data. This buffer
// will be returned by SQLParamData (it is set to the parameter
// number, a 4-byte integer)
byte dataBuf[] = allocBindBuf (ParameterIndex, 4);
// Bind the parameter with SQL_LEN_DATA_AT_EXEC
long buffers[]=new long[4];
buffers[0]=0;
buffers[1]=0;
buffers[2]=0;
buffers[3]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterAtExec (hStmt, ParameterIndex,
SQLtype, length, dataBuf, lenBuf, buffers);
}
//save the native pointers from Garbage Collection
boundParams[ParameterIndex - 1].pA1=buffers[0];
boundParams[ParameterIndex - 1].pA2=buffers[1];
boundParams[ParameterIndex - 1].pB1=buffers[2];
boundParams[ParameterIndex - 1].pB2=buffers[3];
boundParams[ParameterIndex - 1].boundType=SQLtype;
boundParams[ParameterIndex-1].boundValue = x;
// Save the input stream
boundParams[ParameterIndex - 1].setInputStream (x, length);
// Set the stream type
boundParams[ParameterIndex - 1].setStreamType (streamType);
// save value and type for Sql Batch
arrayParams.storeValue( ParameterIndex - 1, (java.io.InputStream)x, length);
setSqlType(ParameterIndex, SQLtype);
}
//--------------------------------------------------------------------
// setChar
// Binds the given string to the given SQL type
//--------------------------------------------------------------------
protected void setChar (
int parameterIndex,
int SQLtype,
int scale,
String x)
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
int precision = 0;
int prefPrecision = 0;
char[] xChars = x.toCharArray();
byte xValue[] = new byte[0];
try {
xValue = CharsToBytes (OdbcApi.charSet, xChars);
} catch (java.io.UnsupportedEncodingException exx) {
throw (Error) (new InternalError("SQL")).initCause(exx);
}
byte bindBuf[] = allocBindBuf (parameterIndex,
(xValue.length));
// Get the precision for this SQL type. If the precision
// is out of bounds, set it to our default
precision = getPrecision(SQLtype);
/*
// COMENTED - OUT for Intersolve Driver
// but brakes (ExpressLane's 2.1 ODBC Driver for these Types!)
//Added for NUMERIC/DECIMAL Types
//Use the String length as the precision
//as long as it is <= the database's Type precision.
//If there is no precision, default to the bridge limits
if ( (SQLtype == Types.NUMERIC) || (SQLtype == Types.DECIMAL) )
{
if (x != null)
{
prefPrecision = (x.trim()).length();
}
if ( prefPrecision > 0 )
{
//throw new SQLException ("Data precision > precision allowed by the Database for this Type");
precision = prefPrecision;
}
}
*/
if ((precision < 0) ||
(precision > JdbcOdbcLimits.DEFAULT_IN_PRECISION))
{
//precision = JdbcOdbcLimits.DEFAULT_IN_PRECISION;
//put in as a fix for invalid precision problems
precision = xValue.length;
}
long buffers[]=new long[4];
buffers[0]=0;
buffers[1]=0;
buffers[2]=0;
buffers[3]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterString (hStmt, parameterIndex,
SQLtype, precision, scale, xValue, bindBuf, buffers);
}
//Save the pointers from the trash
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].pB1=buffers[2];
boundParams[parameterIndex - 1].pB2=buffers[3];
boundParams[parameterIndex - 1].scale = scale;
boundParams[parameterIndex - 1].boundType=SQLtype;
boundParams[parameterIndex-1].boundValue = x;
// save value and type. Also keep track of the
// largest precision/scale values for Sql Batch.
if ( (SQLtype == Types.NUMERIC) || (SQLtype == Types.DECIMAL) )
{
arrayParams.storeValue( parameterIndex - 1, new BigDecimal(x.trim()), OdbcDef.SQL_NTS);
NumberDef = precision;
if (scale > NumberScale)
NumberScale = scale;
}
//bug 4495452
else if ( SQLtype == Types.BIGINT )
{
arrayParams.storeValue( parameterIndex - 1, new BigInteger(x.trim()), OdbcDef.SQL_NTS);
NumberDef = precision;
if (scale > NumberScale)
NumberScale = scale;
}
else
{
arrayParams.storeValue( parameterIndex - 1, (String)x, OdbcDef.SQL_NTS);
StringDef = precision;
}
setSqlType(parameterIndex, SQLtype);
}
//--------------------------------------------------------------------
// setBinary
// Binds the given byte array to the given SQL type
//--------------------------------------------------------------------
protected void setBinary (
int parameterIndex,
int SQLtype,
byte x[])
throws SQLException
{
clearParameter(parameterIndex);
// Indicate that this is an input parameter
setInputParameter (parameterIndex, true);
// Allocate a buffer to be used in binding. This will be
// a 'permanent' buffer that the bridge will fill in with
// the bound data in native format.
byte bindBuf[] = allocBindBuf (parameterIndex,
x.length);
// Get the buffer needed for the length
byte lenBuf[] = getLengthBuf (parameterIndex);
long buffers[]=new long[6];
buffers[0]=0;
buffers[1]=0;
buffers[2]=0;
buffers[3]=0;
buffers[4]=0;
buffers[5]=0;
if (!batchOn)
{
OdbcApi.SQLBindInParameterBinary (hStmt, parameterIndex,
SQLtype, x, bindBuf, lenBuf, buffers);
}
//Save the pointers from the trash
boundParams[parameterIndex - 1].pA1=buffers[0];
boundParams[parameterIndex - 1].pA2=buffers[1];
boundParams[parameterIndex - 1].pB1=buffers[2];
boundParams[parameterIndex - 1].pB2=buffers[3];
boundParams[parameterIndex - 1].pC1=buffers[4];
boundParams[parameterIndex - 1].pC2=buffers[5];
boundParams[parameterIndex - 1].boundType=SQLtype;
boundParams[parameterIndex-1].boundValue = x;
binaryPrec = x.length; // 4532171
//save value and type for Sql Batch
arrayParams.storeValue( parameterIndex - 1, (byte[])x, OdbcDef.SQL_NTS);
setSqlType(parameterIndex, SQLtype);
}
//--------------------------------------------------------------------
// getTypeFromObjectArray
// Given an object Array of unknown type, return the Java SQL type
// representative of all of the Values in the array.
//--------------------------------------------------------------------
protected int getTypeFromObjectArray (Object[] x)
{
int colSetType = Types.OTHER;
for (int i = 0; i < batchSize; i++)
{
colSetType = getTypeFromObject (x[i]);
if ( colSetType != Types.NULL )
{
break;
}
}
return colSetType;
}
public synchronized void close ()
throws SQLException
{
if (OdbcApi.getTracer().isTracing ()) {
OdbcApi.getTracer().trace ("*PreparedStatement.close");
}
// Close/clear our result set
clearMyResultSet ();
// Reset last warning message
try {
clearWarnings ();
if (hStmt != OdbcDef.SQL_NULL_HSTMT) {
//4524683
if(closeCalledFromFinalize == true) {
if( myConnection.isFreeStmtsFromConnectionOnly() == false) {
OdbcApi.SQLFreeStmt (hStmt, OdbcDef.SQL_DROP);
}
}
else {
OdbcApi.SQLFreeStmt (hStmt, OdbcDef.SQL_DROP);
}
hStmt = OdbcDef.SQL_NULL_HSTMT;
FreeParams();
for (int pindex=1; boundParams != null && pindex <= boundParams.length; pindex++)
{
boundParams[pindex-1].binaryData = null;
boundParams[pindex-1].initialize ();
boundParams[pindex-1].paramInputStream = null;
boundParams[pindex-1].inputParameter = false;
}
}
}
catch (SQLException ex) {
// If we get an error, ignore
}
// 4486684 - Deallocate the previous arrays and the global refs that have been allocated in executeBatchUpdate()
FreeIntParams();
// Remove this Statement object from the Connection object's
// list
myConnection.deregisterStatement (this);
if (batchOn)
clearBatch();
}
// 4486684
public synchronized void FreeIntParams()
{
if(pA1 != null)
{
if(pA1[0] != 0)
{
OdbcApi.ReleaseStoredIntegers(pA1[0], pA1[1]);
pA1[0] = 0;
pA1[1] = 0;
}
}
if(pA2 != null)
{
if(pA2[0] != 0)
{
OdbcApi.ReleaseStoredIntegers(pA2[0], pA2[1]);
pA2[0] = 0;
pA2[1] = 0;
}
}
}
public synchronized void FreeParams()
throws NullPointerException
{
try
{
for (int pindex=1; pindex <= boundParams.length; pindex++)
{
if (boundParams[pindex-1].pA1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pA1, boundParams[pindex-1].pA2);
boundParams[pindex-1].pA1=0;
boundParams[pindex-1].pA2=0;
}
if (boundParams[pindex-1].pB1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pB1, boundParams[pindex-1].pB2);
boundParams[pindex-1].pB1=0;
boundParams[pindex-1].pB2=0;
}
if (boundParams[pindex-1].pC1!=0)
{
OdbcApi.ReleaseStoredBytes (boundParams[pindex-1].pC1, boundParams[pindex-1].pC2);
boundParams[pindex-1].pC1=0;
boundParams[pindex-1].pC2=0;
}
if (boundParams[pindex-1].pS1!=0)
{
OdbcApi.ReleaseStoredChars (boundParams[pindex-1].pS1, boundParams[pindex-1].pS2);
boundParams[pindex-1].pS1=0;
boundParams[pindex-1].pS2=0;
}
}
}
catch (NullPointerException npx)
{
//Do nothing
}
}
//--------------------------------------------------------------------
// setSql
// sets the current SQL. Used to build a row count query if needed.
//--------------------------------------------------------------------
public void setSql(String sql)
{
mySql = sql.toUpperCase();
}
//--------------------------------------------------------------------
// getObject
// returns and Object[] copy for values in the Parameters. Used in a
// row count query.
//--------------------------------------------------------------------
public Object[] getObjects()
{
Object[] objs = new Object[numParams];
Object[] data = arrayParams.getStoredParameterSet();
if (data != null)
{
try
{
for (int i = 0; i < numParams; i++)
{
objs[i] = data[i];
}
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println("Exception, while calculating row count: " + e.getMessage());
e.printStackTrace();
}
}
return objs;
}
//--------------------------------------------------------------------
// getObjectTypes
// returns and int[] array with the SQL type for each parameter. Used
// in a row count query.
//--------------------------------------------------------------------
public int[] getObjectTypes()
{
int[] types = new int[numParams];
for (int i = 0; i < numParams; i++)
{
types[i] = boundParams[i].getSqlType ();
}
return types;
}
//--------------------------------------------------------------------
// getParamCount
// return the number of Parameters in this Statement.
//--------------------------------------------------------------------
public int getParamCount()
{
return numParams;
}
//--------------------------------------------------------------------
// setInputParameter
// Sets the input parameter flag
//--------------------------------------------------------------------
protected void setInputParameter (
int index,
boolean input)
{
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
boundParams[index - 1].setInputParameter (input);
}
}
//----------------------------------------------------------------
// JDBC 3.0 API Changes
//----------------------------------------------------------------
public void setURL(int i, java.net.URL url) throws SQLException {
throw new UnsupportedOperationException();
}
public ParameterMetaData getParameterMetaData() throws SQLException {
throw new UnsupportedOperationException();
}
//====================================================================
// Data attributes
//====================================================================
protected int numParams; // Number of parameter markers
// for the prepared statement
protected JdbcOdbcBoundParam boundParams[];
// Array of bound parameter
// objects. Each parameter
// marker will have a
// corresponding object to
// hold bind information, and
// resulting data.
protected JdbcOdbcBoundArrayOfParams
arrayParams; // Array of Parameters manipulator.
protected Vector batchSqlVec; // Vector that holds parameter
// values for Batch Updates.
protected boolean batchSupport; // Determines if the Batch Updates
// are supported by the ODBC Driver
protected boolean batchParamsOn; // Determines if arrays of Parameters
// are being used for Batch Updates.
protected int batchSize; // The # of rows for columWise parameter Sets.
protected int arrayDef; // Maximum precision for Arrays of Strings.
protected int arrayScale; // Maximum scale for Arrays of Numeric/Decimals.
protected int StringDef; // Maximum String precision for emulation.
protected int NumberDef; // Maximum Numeric precision for emulation.
protected int NumberScale; // Maximum Numeric scale for emulation.
protected int batchRCFlag; // Row-Count type indicator for Batch Updates.
protected int[] paramsProcessed; // Parameters Processed Pointer for arrays in batch.
protected int[] paramStatusArray; // Parameters Status Pointer for arrays in batch.
//4486684
protected long[] pA1; //paramsProcessed native pointers
protected long[] pA2; //paramStatusArray native pointers
protected int binaryPrec; // 4532171
protected JdbcOdbcUtils utils = new JdbcOdbcUtils();
}