--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.jdbc.EmbedPreparedStatement\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.jdbc;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.types.VariableSizeDataValue;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+import org.apache.derby.iapi.sql.PreparedStatement;\r
+import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.ParameterValueSet;\r
+import org.apache.derby.iapi.sql.ResultDescription;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.RawToBinaryFormatStream;\r
+import org.apache.derby.iapi.types.ReaderToUTF8Stream;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.io.LimitReader;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.reference.JDBC40Translation;\r
+import org.apache.derby.iapi.reference.JDBC30Translation;\r
+import org.apache.derby.iapi.reference.JDBC20Translation;\r
+\r
+import java.util.Calendar;\r
+import java.util.Vector;\r
+\r
+/*\r
+ We would import these, but have name-overlap\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+*/\r
+import java.sql.ResultSetMetaData;\r
+import java.sql.SQLException;\r
+import java.sql.Date;\r
+import java.sql.Time;\r
+import java.sql.Timestamp;\r
+import java.sql.Clob;\r
+import java.sql.Blob;\r
+\r
+import java.io.InputStream;\r
+import java.io.DataInputStream;\r
+import java.io.IOException;\r
+import java.io.EOFException;\r
+import java.io.Reader;\r
+import java.sql.Types;\r
+\r
+import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;\r
+import org.apache.derby.iapi.jdbc.EngineParameterMetaData;\r
+import org.apache.derby.iapi.jdbc.EnginePreparedStatement;\r
+\r
+/**\r
+ *\r
+ * EmbedPreparedStatement is a local JDBC statement.\r
+ <P><B>Supports</B>\r
+ <UL>\r
+ <LI> JSR169\r
+ </UL>\r
+ */\r
+public abstract class EmbedPreparedStatement\r
+ extends EmbedStatement\r
+ implements EnginePreparedStatement\r
+{\r
+\r
+ //Moving jdbc2.0 batch related code in this class because callableStatement in jdbc 20 needs\r
+ //this code too and it doesn't derive from prepared statement in jdbc 20 in our implementation.\r
+\r
+ protected ResultSetMetaData rMetaData;\r
+ //bug 4579-If the prepared statement was revalidated after doing getMetaData(), we\r
+ //should get the metadata info again on next getMetaData(). We store the generated\r
+ //class name in following variable during getMetaData() call. If it differs from the\r
+ //current generated class name, then that indicates a refetch of metadata is required.\r
+ private String gcDuringGetMetaData;\r
+\r
+ protected PreparedStatement preparedStatement;\r
+ private Activation activation;\r
+ \r
+ private BrokeredConnectionControl bcc=null;\r
+\r
+ /*\r
+ Constructor assumes caller will setup context stack\r
+ and restore it.\r
+ */\r
+ public EmbedPreparedStatement (EmbedConnection conn, String sql, boolean forMetaData,\r
+ int resultSetType, int resultSetConcurrency,\r
+ int resultSetHoldability,\r
+ int autoGeneratedKeys,\r
+ int[] columnIndexes,\r
+ String[] columnNames)\r
+ throws SQLException {\r
+\r
+ super(conn, forMetaData, resultSetType, resultSetConcurrency, resultSetHoldability);\r
+ // PreparedStatement is poolable by default\r
+ isPoolable = true;\r
+\r
+ // if the sql string is null, raise an error\r
+ if (sql == null)\r
+ throw newSQLException(SQLState.NULL_SQL_TEXT);\r
+\r
+ // set up the SQLText in EmbedStatement\r
+ SQLText = sql;\r
+\r
+ try {\r
+ preparedStatement = lcc.prepareInternalStatement\r
+ (lcc.getDefaultSchema(), sql, resultSetConcurrency==JDBC20Translation.CONCUR_READ_ONLY, forMetaData);\r
+ \r
+ addWarning(preparedStatement.getCompileTimeWarnings());\r
+\r
+ activation = preparedStatement.getActivation(lcc, resultSetType == JDBC20Translation.TYPE_SCROLL_INSENSITIVE);\r
+\r
+ checkRequiresCallableStatement(activation);\r
+\r
+ //bug 4838 - save the auto-generated key information in activation. keeping this\r
+ //information in lcc will not work work as it can be tampered by a nested trasaction\r
+ if (autoGeneratedKeys == JDBC30Translation.RETURN_GENERATED_KEYS)\r
+ activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);\r
+\r
+ } catch (Throwable t) {\r
+ throw handleException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ JDBC states that a Statement is closed when garbage collected.\r
+\r
+ @exception Throwable Allows any exception to be thrown during finalize\r
+ */\r
+ protected void finalize() throws Throwable {\r
+ super.finalize();\r
+\r
+ /*\r
+ ** We mark the activation as not being used and\r
+ ** that is it. We rely on the connection to sweep\r
+ ** through the activations to find the ones that\r
+ ** aren't in use, and to close them. We cannot\r
+ ** do a activation.close() here because there are\r
+ ** synchronized methods under close that cannot\r
+ ** be called during finalization.\r
+ */\r
+ if (activation != null) \r
+ {\r
+ activation.markUnused();\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Statement interface\r
+ we override all Statement methods that take a SQL\r
+ string as they must thrown an exception in a PreparedStatement.\r
+ See the JDBC 3.0 spec.\r
+ */\r
+ public final boolean execute(String sql) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String)");\r
+ }\r
+ public final boolean execute(String sql, int autoGenKeys) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, int)");\r
+ }\r
+ public final boolean execute(String sql, int[] columnIndexes) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, int[])");\r
+ }\r
+ public final boolean execute(String sql, String[] columnNames) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, String[])");\r
+ }\r
+ public final java.sql.ResultSet executeQuery(String sql) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeQuery(String)");\r
+ }\r
+ public final int executeUpdate(String sql) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String)");\r
+ }\r
+ public final int executeUpdate(String sql, int autoGenKeys) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, int)");\r
+ }\r
+ public final int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, int[])");\r
+ }\r
+ public final int executeUpdate(String sql, String[] columnNames) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, String[])");\r
+ }\r
+ public final void addBatch(String sql) throws SQLException {\r
+ throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "addBatch(String)");\r
+ }\r
+\r
+\r
+ /**\r
+ * Additional close to close our activation.\r
+ * In the case that a XAConnection is involved in the creation of this\r
+ * PreparedStatement for e.g in the following case\r
+ *\r
+ * <code>\r
+ * XAConnection xaconn = xadatasource.getXAConnection();//where xadatasource is an object of XADataSource\r
+ * Connection conn = xaconnection.getConnection();\r
+ * PreparedStatement ps = conn.preparedStatement("values 1");\r
+ * </code>\r
+ *\r
+ * In the above case the PreparedStatement will actually be a \r
+ * BrokeredPreparedStatement40 object. Hence when we call \r
+ * bcc.onStatementClose and pass the PreparedStatement that caused it\r
+ * applicationStatement will be the appropriate choice since it will \r
+ * contain the appropriate instance of PreparedStatement in each case\r
+ *\r
+ * @throws SQLException upon failure\r
+ *\r
+ */\r
+ void closeActions() throws SQLException {\r
+\r
+ if (bcc!=null) {\r
+ java.sql.PreparedStatement ps_app = \r
+ (java.sql.PreparedStatement)applicationStatement;\r
+ bcc.onStatementClose(ps_app);\r
+ }\r
+ //we release the resource for preparedStatement\r
+ preparedStatement = null;\r
+\r
+ try{\r
+ setupContextStack();\r
+ } catch (SQLException se) {\r
+ //we may have already committed the transaction in which case\r
+ //setupContextStack will fail, the close should just return\r
+ return;\r
+ }\r
+ try\r
+ {\r
+ activation.close();\r
+ activation = null;\r
+ } catch (Throwable t)\r
+ {\r
+ throw handleException(t);\r
+ } finally {\r
+ restoreContextStack();\r
+ }\r
+ }\r
+ \r
+ /*\r
+ * PreparedStatement interface; we have inherited from\r
+ * EmbedStatement to get the Statement interface for\r
+ * EmbedPreparedStatement (needed by PreparedStatement)\r
+ * These are the JDBC interface comments, so we know\r
+ * what to do.\r
+ */\r
+\r
+ /**\r
+ * A prepared SQL query is executed and its ResultSet is returned.\r
+ *\r
+ * @return a ResultSet that contains the data produced by the\r
+ * query; never null\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final java.sql.ResultSet executeQuery() throws SQLException {\r
+ try {\r
+ executeStatement(activation, true, false);\r
+ } catch(SQLException sqle) {\r
+ checkStatementValidity(sqle);\r
+ }\r
+ \r
+ if (SanityManager.DEBUG) {\r
+ if (results == null)\r
+ SanityManager.THROWASSERT("no results returned on executeQuery()");\r
+ }\r
+ \r
+ return results;\r
+ }\r
+\r
+ /**\r
+ * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,\r
+ * SQL statements that return nothing such as SQL DDL statements\r
+ * can be executed.\r
+ *\r
+ * @return either the row count for INSERT, UPDATE or DELETE; or 0\r
+ * for SQL statements that return nothing\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final int executeUpdate() throws SQLException {\r
+ try {\r
+ executeStatement(activation, false, true);\r
+ } catch(SQLException sqle) {\r
+ checkStatementValidity(sqle);\r
+ }\r
+ return updateCount;\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to SQL NULL.\r
+ *\r
+ * <P><B>Note:</B> You must specify the parameter's SQL type.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param sqlType SQL type code defined by java.sql.Types\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {\r
+\r
+ checkForSupportedDataType(sqlType);\r
+ checkStatus();\r
+\r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+ \r
+ if (!DataTypeDescriptor.isJDBCTypeEquivalent(jdbcTypeId, sqlType)) {\r
+\r
+ throw dataTypeConversion(parameterIndex, Util.typeName(sqlType));\r
+ }\r
+ \r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setToNull();\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java boolean value. According to the JDBC API spec,\r
+ * the driver converts this to a SQL BIT value when it sends it to the\r
+ * database. But we don't have to do this, since the database engine\r
+ * supports a boolean type.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setBoolean(int parameterIndex, boolean x) throws SQLException {\r
+ \r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java byte value. The driver converts this\r
+ * to a SQL TINYINT value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setByte(int parameterIndex, byte x) throws SQLException {\r
+\r
+ checkStatus();\r
+ try {\r
+\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java short value. The driver converts this\r
+ * to a SQL SMALLINT value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setShort(int parameterIndex, short x) throws SQLException {\r
+\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java int value. The driver converts this\r
+ * to a SQL INTEGER value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setInt(int parameterIndex, int x) throws SQLException {\r
+ checkStatus();\r
+\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java long value. The driver converts this\r
+ * to a SQL BIGINT value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setLong(int parameterIndex, long x) throws SQLException {\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java float value. The driver converts this\r
+ * to a SQL FLOAT value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setFloat(int parameterIndex, float x) throws SQLException {\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java double value. The driver converts this\r
+ * to a SQL DOUBLE value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setDouble(int parameterIndex, double x) throws SQLException {\r
+ checkStatus();\r
+\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java String value. The driver converts this\r
+ * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments\r
+ * size relative to the driver's limits on VARCHARs) when it sends\r
+ * it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setString(int parameterIndex, String x) throws SQLException {\r
+ checkStatus(); \r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a Java array of bytes. The driver converts\r
+ * this to a SQL VARBINARY or LONGVARBINARY (depending on the\r
+ * argument's size relative to the driver's limits on VARBINARYs)\r
+ * when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value \r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException {\r
+ checkStatus();\r
+\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a java.sql.Date value. The driver converts this\r
+ * to a SQL DATE value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setDate(int parameterIndex, Date x) throws SQLException {\r
+ setDate( parameterIndex, x, (Calendar) null);\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a java.sql.Time value. The driver converts this\r
+ * to a SQL TIME value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setTime(int parameterIndex, Time x) throws SQLException {\r
+ setTime( parameterIndex, x, (Calendar) null);\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a java.sql.Timestamp value. The driver\r
+ * converts this to a SQL TIMESTAMP value when it sends it to the\r
+ * database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value \r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setTimestamp(int parameterIndex, Timestamp x)\r
+ throws SQLException {\r
+ setTimestamp( parameterIndex, x, (Calendar) null);\r
+ }\r
+\r
+ /**\r
+ * We do this inefficiently and read it all in here. The target type\r
+ * is assumed to be a String.\r
+ * \r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the ASCII parameter value\r
+ * @param length the number of bytes in the stream \r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setAsciiStream(int parameterIndex, InputStream x, long length)\r
+ throws SQLException {\r
+ checkAsciiStreamConditions(parameterIndex);\r
+ java.io.Reader r = null;\r
+\r
+ if (x != null)\r
+ {\r
+ // Use ISO-8859-1 and not US-ASCII as JDBC seems to define\r
+ // ASCII as 8 bits. US-ASCII is 7.\r
+ try {\r
+ r = new java.io.InputStreamReader(x, "ISO-8859-1");\r
+ } catch (java.io.UnsupportedEncodingException uee) {\r
+ throw new SQLException(uee.getMessage());\r
+ }\r
+ }\r
+\r
+ setCharacterStreamInternal(parameterIndex, r, false, length);\r
+ }\r
+\r
+ /**\r
+ * We do this inefficiently and read it all in here. The target type\r
+ * is assumed to be a String.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the ASCII parameter value\r
+ * @param length the number of bytes in the stream\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+\r
+ public final void setAsciiStream(int parameterIndex, InputStream x, int length)\r
+ throws SQLException {\r
+ setAsciiStream(parameterIndex,x,(long)length);\r
+ }\r
+\r
+\r
+ /**\r
+ Deprecated in JDBC 3.0\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the\r
+ * UNICODE parameter value\r
+ * @param length the number of bytes in the stream\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void setUnicodeStream(int parameterIndex, InputStream x, int length)\r
+ throws SQLException\r
+ {\r
+ throw Util.notImplemented("setUnicodeStream");\r
+ }\r
+\r
+ /**\r
+ * When a very large UNICODE value is input to a LONGVARCHAR\r
+ * parameter, it may be more practical to send it via a\r
+ * java.io.Reader. JDBC will read the data from the stream\r
+ * as needed, until it reaches end-of-file. The JDBC driver will\r
+ * do any necessary conversion from UNICODE to the database char format.\r
+ *\r
+ * <P><B>Note:</B> This stream object can either be a standard\r
+ * Java stream object or your own subclass that implements the\r
+ * standard interface.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param reader the java reader which contains the UNICODE data\r
+ * @param length the number of characters in the stream\r
+ * @exception SQLException if a database-access error occurs.\r
+ */\r
+ public final void setCharacterStream(int parameterIndex,\r
+ java.io.Reader reader,\r
+ long length) throws SQLException {\r
+ checkCharacterStreamConditions(parameterIndex);\r
+ setCharacterStreamInternal(parameterIndex, reader, false, length);\r
+ }\r
+\r
+ /**\r
+ * When a very large UNICODE value is input to a LONGVARCHAR\r
+ * parameter, it may be more practical to send it via a\r
+ * java.io.Reader. JDBC will read the data from the stream\r
+ * as needed, until it reaches end-of-file. The JDBC driver will\r
+ * do any necessary conversion from UNICODE to the database char format.\r
+ *\r
+ * <P><B>Note:</B> This stream object can either be a standard\r
+ * Java stream object or your own subclass that implements the\r
+ * standard interface.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param reader the java reader which contains the UNICODE data\r
+ * @param length the number of characters in the stream\r
+ * @exception SQLException if a database-access error occurs.\r
+ */\r
+ public final void setCharacterStream(int parameterIndex,\r
+ java.io.Reader reader,\r
+ int length) throws SQLException {\r
+ setCharacterStream(parameterIndex,reader,(long)length);\r
+ }\r
+\r
+ /**\r
+ * Check general preconditions for setCharacterStream methods.\r
+ *\r
+ * @param parameterIndex 1-based index of the parameter.\r
+ */\r
+ private final void checkCharacterStreamConditions(int parameterIndex)\r
+ throws SQLException {\r
+ checkStatus();\r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+ if (!DataTypeDescriptor.isCharacterStreamAssignable(jdbcTypeId)) {\r
+ throw dataTypeConversion(parameterIndex, "java.io.Reader");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Check general preconditions for setAsciiStream methods.\r
+ *\r
+ * @param parameterIndex 1-based index of the parameter.\r
+ */\r
+ private final void checkAsciiStreamConditions(int parameterIndex)\r
+ throws SQLException {\r
+ checkStatus();\r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+ if (!DataTypeDescriptor.isAsciiStreamAssignable(jdbcTypeId)) {\r
+ throw dataTypeConversion(parameterIndex,\r
+ "java.io.InputStream(ASCII)");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set the given character stream for the specified parameter.\r
+ *\r
+ * If <code>lengthLess</code> is <code>true</code>, the following\r
+ * conditions are either not checked or verified at the execution time\r
+ * of the prepared statement:\r
+ * <ol><li>If the stream length is negative.\r
+ * <li>If the stream's actual length equals the specified length.</ol>\r
+ * The <code>lengthLess</code> variable was added to differentiate between\r
+ * streams with invalid lengths and streams without known lengths.\r
+ *\r
+ * @param parameterIndex the 1-based index of the parameter to set.\r
+ * @param reader the data.\r
+ * @param lengthLess tells whether we know the length of the data or not.\r
+ * @param length the length of the data. Ignored if <code>lengthLess</code>\r
+ * is <code>true</code>.\r
+ */\r
+ private void setCharacterStreamInternal(int parameterIndex,\r
+ Reader reader,\r
+ final boolean lengthLess,\r
+ long length)\r
+ throws SQLException\r
+ {\r
+ // Check for negative length if length is specified.\r
+ if (!lengthLess && length < 0)\r
+ throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);\r
+\r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+\r
+\r
+ if (reader == null) {\r
+ setNull(parameterIndex, jdbcTypeId);\r
+ return;\r
+ }\r
+\r
+ /*\r
+ The value stored should not exceed the maximum value that can be \r
+ stored in an integer \r
+ This checking needs to be done because currently derby does not\r
+ support Clob sizes greater than 2G-1 \r
+ */\r
+ if (!lengthLess && length > Integer.MAX_VALUE)\r
+ throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,\r
+ getParameterSQLType(parameterIndex));\r
+\r
+ try {\r
+ ReaderToUTF8Stream utfIn;\r
+ ParameterValueSet pvs = getParms();\r
+ // Need column width to figure out if truncation is needed\r
+ DataTypeDescriptor dtd[] = preparedStatement\r
+ .getParameterTypes();\r
+ int colWidth = dtd[parameterIndex - 1].getMaximumWidth();\r
+ // Default to max column width. This will be used to limit the\r
+ // amount of data read when operating on "lengthless" streams.\r
+ int usableLength = colWidth;\r
+\r
+ if (!lengthLess) {\r
+ // We cast the length from long to int. This wouldn't be\r
+ // appropriate if the limit of 2G-1 is decided to be increased\r
+ // at a later stage.\r
+ int intLength = (int)length;\r
+ int truncationLength = 0;\r
+\r
+ usableLength = intLength;\r
+\r
+ // Currently long varchar does not allow for truncation of\r
+ // trailing blanks.\r
+ // For char and varchar types, current mechanism of\r
+ // materializing when using streams seems fine given their max\r
+ // limits.\r
+ // This change is fix for DERBY-352: Insert of clobs using\r
+ // streams should not materialize the entire stream into memory\r
+ // In case of clobs, the truncation of trailing blanks is\r
+ // factored in when reading from the stream without\r
+ // materializing the entire stream, and so the special casing\r
+ // for clob below.\r
+ if (jdbcTypeId == Types.CLOB)\r
+ {\r
+\r
+ // It is possible that the length of the stream passed in\r
+ // is greater than the column width, in which case the data\r
+ // from the stream needs to be truncated.\r
+ // usableLength is the length of the data from stream that\r
+ // can be inserted which is min(colWidth,length) provided\r
+ // length - colWidth has trailing blanks only\r
+ // we have used intLength into which the length variable had\r
+ // been cast to an int and stored\r
+ if (intLength > colWidth) {\r
+ usableLength = colWidth;\r
+ truncationLength = intLength - usableLength;\r
+ }\r
+ }\r
+ // Create a stream with truncation.\r
+ utfIn = new ReaderToUTF8Stream(reader, usableLength,\r
+ truncationLength, getParameterSQLType(parameterIndex));\r
+ } else {\r
+ // Create a stream without exactness checks,\r
+ // but with a maximum limit.\r
+ utfIn = new ReaderToUTF8Stream(reader, colWidth,\r
+ getParameterSQLType(parameterIndex));\r
+ }\r
+\r
+ // JDBC is one-based, DBMS is zero-based.\r
+ // Note that for lengthless stream, usableLength will be\r
+ // the maximum length for the column. \r
+ // This is okay, based on the observation that\r
+ // setValue does not use the value for anything at all.\r
+ pvs.getParameterForSet(\r
+ parameterIndex - 1).setValue(utfIn, usableLength);\r
+\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to the given input stream.\r
+ * When a very large binary value is input to a <code>LONGVARBINARY</code>\r
+ * parameter, it may be more practical to send it via a\r
+ * <code>java.io.InputStream</code> object. The data will be read from the\r
+ * stream as needed until end-of-file is reached.\r
+ *\r
+ * <em>Note:</em> This stream object can either be a standard Java stream\r
+ * object or your own subclass that implements the standard interface.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the binary parameter value\r
+ * @throws SQLException if a database access error occurs or this method is\r
+ * called on a closed <code>PreparedStatement</code>\r
+ */\r
+ public void setBinaryStream(int parameterIndex, InputStream x)\r
+ throws SQLException {\r
+ checkBinaryStreamConditions(parameterIndex);\r
+ setBinaryStreamInternal(parameterIndex, x, true, -1);\r
+ }\r
+\r
+ /**\r
+ * sets the parameter to the Binary stream\r
+ * \r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the binary parameter value\r
+ * @param length the number of bytes in the stream \r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setBinaryStream(int parameterIndex, InputStream x, long length)\r
+ throws SQLException {\r
+ checkBinaryStreamConditions(parameterIndex);\r
+ setBinaryStreamInternal(parameterIndex, x, false, length);\r
+ }\r
+\r
+ /**\r
+ * sets the parameter to the binary stream\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the java input stream which contains the binary parameter value\r
+ * @param length the number of bytes in the stream\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setBinaryStream(int parameterIndex, InputStream x, int length)\r
+ throws SQLException {\r
+ setBinaryStream(parameterIndex,x,(long)length);\r
+ }\r
+\r
+ /**\r
+ * Set the given stream for the specified parameter.\r
+ *\r
+ * If <code>lengthLess</code> is <code>true</code>, the following\r
+ * conditions are either not checked or verified at the execution time\r
+ * of the prepared statement:\r
+ * <ol><li>If the stream length is negative.\r
+ * <li>If the stream's actual length equals the specified length.</ol>\r
+ * The <code>lengthLess</code> variable was added to differentiate between\r
+ * streams with invalid lengths and streams without known lengths.\r
+ *\r
+ * @param parameterIndex the 1-based index of the parameter to set.\r
+ * @param x the data.\r
+ * @param lengthLess tells whether we know the length of the data or not.\r
+ * @param length the length of the data. Ignored if <code>lengthLess</code>\r
+ * is <code>true</code>.\r
+ */\r
+ private void setBinaryStreamInternal(int parameterIndex, InputStream x,\r
+ final boolean lengthLess, long length)\r
+ throws SQLException\r
+ {\r
+\r
+ if ( !lengthLess && length < 0 )\r
+ throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);\r
+ \r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+ if (x == null) {\r
+ setNull(parameterIndex, jdbcTypeId);\r
+ return;\r
+ }\r
+ \r
+ // max number of bytes that can be set to be inserted \r
+ // in Derby is 2Gb-1 (ie Integer.MAX_VALUE). \r
+ // (e.g into a blob column).\r
+ // For now, we cast the length from long to int as a result.\r
+ // If we ever decide to increase these limits for lets say blobs, \r
+ // in that case the cast to int would not be appropriate.\r
+ if ( !lengthLess && length > Integer.MAX_VALUE ) {\r
+ throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,\r
+ getEmbedParameterSetMetaData().getParameterTypeName(\r
+ parameterIndex));\r
+ }\r
+\r
+ try {\r
+ RawToBinaryFormatStream rawStream;\r
+ if (lengthLess) {\r
+ // Force length to -1 for good measure.\r
+ length = -1;\r
+ DataTypeDescriptor dtd[] = \r
+ preparedStatement.getParameterTypes();\r
+ rawStream = new RawToBinaryFormatStream(x,\r
+ dtd[parameterIndex -1].getMaximumWidth(),\r
+ dtd[parameterIndex -1].getTypeName());\r
+ } else {\r
+ rawStream = new RawToBinaryFormatStream(x, (int)length);\r
+ }\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(\r
+ rawStream, (int)length);\r
+\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Check general preconditions for setBinaryStream methods.\r
+ *\r
+ * @param parameterIndex 1-based index of the parameter.\r
+ */\r
+ private final void checkBinaryStreamConditions(int parameterIndex)\r
+ throws SQLException {\r
+ checkStatus();\r
+ int jdbcTypeId = getParameterJDBCType(parameterIndex);\r
+ if (!DataTypeDescriptor.isBinaryStreamAssignable(jdbcTypeId)) {\r
+ throw dataTypeConversion(parameterIndex, "java.io.InputStream");\r
+ }\r
+ }\r
+\r
+ /////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // JDBC 2.0 - New public methods\r
+ //\r
+ /////////////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ *\r
+ * JDBC 2.0\r
+ *\r
+ * Sets the designated parameter to SQL <code>NULL</code>.\r
+ * This version of the method <code>setNull</code> should\r
+ * be used for user-defined types and REF type parameters. Examples\r
+ * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and\r
+ * named array types.\r
+ *\r
+ * @param paramIndex the first parameter is 1, the second is 2, ...\r
+ * @param sqlType a value from <code>java.sql.Types</code>\r
+ * @param typeName the fully-qualified name of an SQL user-defined type;\r
+ * ignored if the parameter is not a user-defined type or REF\r
+ * @exception SQLException if a database access error occurs or\r
+ * this method is called on a closed <code>PreparedStatement</code>\r
+ * @exception SQLFeatureNotSupportedException if <code>sqlType</code> is\r
+ * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,\r
+ * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,\r
+ * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,\r
+ * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>\r
+ * or <code>STRUCT</code> data type and the JDBC driver does not support\r
+ * this data type or if the JDBC driver does not support this method\r
+ *\r
+ */\r
+ public void setNull(int paramIndex,\r
+ int sqlType,\r
+ String typeName)\r
+ throws SQLException {\r
+ setNull(paramIndex,sqlType);\r
+ }\r
+\r
+ /**\r
+ * JDBC 2.0\r
+ *\r
+ * Add a set of parameters to the batch.\r
+ * \r
+ * @exception SQLException if a database-access error occurs.\r
+ */\r
+ public void addBatch() throws SQLException {\r
+ checkStatus();\r
+\r
+ // need to synchronized to ensure that two threads\r
+ // don't both create a Vector at the same time. This\r
+ // would lead to one of the set of parameters being thrown\r
+ // away\r
+ synchronized (getConnectionSynchronization()) {\r
+ if (batchStatements == null)\r
+ batchStatements = new Vector();\r
+\r
+ //get a clone of the parameterValueSet and save it in the vector\r
+ //which will be used later on at the time of batch execution.\r
+ //This way we will get a copy of the current statement's parameter\r
+ //values rather than a pointer to the statement's parameter value\r
+ //set which will change with every new statement in the batch.\r
+ batchStatements.addElement(getParms().getClone());\r
+ clearParameters();\r
+ }\r
+ }\r
+\r
+ boolean executeBatchElement(Object batchElement) throws SQLException, StandardException {\r
+ \r
+ ParameterValueSet temp = (ParameterValueSet) batchElement;\r
+\r
+ int numberOfParameters = temp.getParameterCount();\r
+\r
+ for (int j=0; j<numberOfParameters; j++) {\r
+ temp.getParameter(j).setInto(this, j + 1);\r
+ }\r
+\r
+ return super.executeStatement(activation, false, true);\r
+ }\r
+\r
+ \r
+\r
+ /**\r
+ * <P>In general, parameter values remain in force for repeated use of a\r
+ * Statement. Setting a parameter value automatically clears its\r
+ * previous value. However, in some cases it is useful to immediately\r
+ * release the resources used by the current parameter values; this can\r
+ * be done by calling clearParameters.\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public void clearParameters() throws SQLException {\r
+ checkStatus();\r
+\r
+ ParameterValueSet pvs = getParms();\r
+ if (pvs != null)\r
+ pvs.clearParameters();\r
+ }\r
+\r
+ /**\r
+ * JDBC 2.0\r
+ *\r
+ * The number, types and properties of a ResultSet's columns\r
+ * are provided by the getMetaData method.\r
+ *\r
+ * @return the description of a ResultSet's columns\r
+ * @exception SQLException Feature not implemented for now.\r
+ */\r
+ public java.sql.ResultSetMetaData getMetaData() throws SQLException\r
+ {\r
+ checkExecStatus();\r
+ synchronized (getConnectionSynchronization())\r
+ {\r
+ //reason for casting is getActivationClass is not available on PreparedStatement\r
+ ExecPreparedStatement execp = (ExecPreparedStatement)preparedStatement;\r
+\r
+ setupContextStack(); // make sure there's context\r
+\r
+ try {\r
+ //bug 4579 - if the statement is invalid, regenerate the metadata info\r
+ if (preparedStatement.isValid() == false)\r
+ {\r
+ //need to revalidate the statement here, otherwise getResultDescription would\r
+ //still have info from previous valid statement\r
+ preparedStatement.rePrepare(lcc);\r
+ rMetaData = null;\r
+ }\r
+ //bug 4579 - gcDuringGetMetaData will be null if this is the first time\r
+ //getMetaData call is made.\r
+ //Second check - if the statement was revalidated since last getMetaData call,\r
+ //then gcDuringGetMetaData wouldn't match with current generated class name\r
+ if (gcDuringGetMetaData == null || gcDuringGetMetaData.equals(execp.getActivationClass().getName()) == false)\r
+ {\r
+ rMetaData = null;\r
+ gcDuringGetMetaData = execp.getActivationClass().getName();\r
+ }\r
+ if (rMetaData == null)\r
+ {\r
+ ResultDescription resd = preparedStatement.getResultDescription();\r
+ if (resd != null)\r
+ {\r
+ // Internally, the result description has information\r
+ // which is used for insert, update and delete statements\r
+ // Externally, we decided that statements which don't\r
+ // produce result sets such as insert, update and delete\r
+ // should not return ResultSetMetaData. This is enforced\r
+ // here\r
+ String statementType = resd.getStatementType();\r
+ if (statementType.equals("INSERT") ||\r
+ statementType.equals("UPDATE") ||\r
+ statementType.equals("DELETE"))\r
+ rMetaData = null;\r
+ else\r
+ rMetaData = newEmbedResultSetMetaData(resd);\r
+ }\r
+ }\r
+ } catch (Throwable t) {\r
+ throw handleException(t);\r
+ } finally {\r
+ restoreContextStack();\r
+ }\r
+ }\r
+ return rMetaData;\r
+ }\r
+\r
+ //----------------------------------------------------------------------\r
+ // Advanced features:\r
+\r
+ /**\r
+ * The interface says that the type of the Object parameter must\r
+ * be compatible with the type of the targetSqlType. We check that,\r
+ * and if it flies, we expect the underlying engine to do the\r
+ * required conversion once we pass in the value using its type.\r
+ * So, an Integer converting to a CHAR is done via setInteger()\r
+ * support on the underlying CHAR type.\r
+ *\r
+ * <p>If x is null, it won't tell us its type, so we pass it on to setNull\r
+ *\r
+ * @param parameterIndex The first parameter is 1, the second is 2, ...\r
+ * @param x The object containing the input parameter value\r
+ * @param targetSqlType The SQL type (as defined in java.sql.Types) to be \r
+ * sent to the database. The scale argument may further qualify this type.\r
+ * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types\r
+ * this is the number of digits after the decimal. For all other\r
+ * types this value will be ignored,\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setObject(int parameterIndex, Object x, int targetSqlType, int scale)\r
+ throws SQLException {\r
+\r
+ if (x == null) {\r
+ setNull(parameterIndex, targetSqlType);\r
+ return;\r
+ }\r
+\r
+ checkForSupportedDataType(targetSqlType);\r
+\r
+ int paramJDBCType = getParameterJDBCType(parameterIndex);\r
+\r
+ if (paramJDBCType != java.sql.Types.JAVA_OBJECT) {\r
+ if (!DataTypeDescriptor.isJDBCTypeEquivalent(paramJDBCType, targetSqlType)) {\r
+ throw dataTypeConversion(parameterIndex, Util.typeName(targetSqlType));\r
+ }\r
+ }\r
+\r
+ setObject(parameterIndex, x);\r
+ \r
+ /*\r
+ * If the parameter type is DECIMAL or NUMERIC, then\r
+ * we need to set the correct scale or set it \r
+ * to the default which is zero for setObject.\r
+ */\r
+ if ((paramJDBCType == Types.DECIMAL) || \r
+ (paramJDBCType == Types.NUMERIC))\r
+ {\r
+ setScale(parameterIndex, scale);\r
+ } \r
+ }\r
+\r
+ /**\r
+ * This method is like setObject above, but assumes a scale of zero.\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setObject(int parameterIndex, Object x, int targetSqlType)\r
+ throws SQLException {\r
+ setObject(parameterIndex, x, targetSqlType, 0);\r
+ }\r
+\r
+ /**\r
+ * <p>Set the value of a parameter using an object; use the\r
+ * java.lang equivalent objects for integral values.\r
+ *\r
+ * <p>The JDBC specification specifies a standard mapping from\r
+ * Java Object types to SQL types. The given argument java object\r
+ * will be converted to the corresponding SQL type before being\r
+ * sent to the database.\r
+ *\r
+ * <p>Note that this method may be used to pass datatabase\r
+ * specific abstract data types, by using a Driver specific Java\r
+ * type.\r
+ *\r
+ * @param parameterIndex The first parameter is 1, the second is 2, ...\r
+ * @param x The object containing the input parameter value \r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final void setObject(int parameterIndex, Object x) throws SQLException {\r
+ checkStatus(); \r
+\r
+\r
+ int colType = getParameterJDBCType(parameterIndex);\r
+\r
+ // JDBC Tutorial and Reference books states in the PreparedStatement\r
+ // overview, that passing a untyped null into setObject() is not allowed.\r
+ // JCC disallows this, basically SQL can not handle a untyped NULL.\r
+ // Section 25.1.6 (Third edition), 24.1.5 (Second Edition)\r
+\r
+ if (x == null) {\r
+ //setNull(parameterIndex, colType);\r
+ //return;\r
+ throw dataTypeConversion(parameterIndex, "null");\r
+ }\r
+ \r
+ if (colType == org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT) {\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().setParameterAsObject(parameterIndex - 1, x);\r
+ return;\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+\r
+ // Need to do instanceof checks here so that the behaviour\r
+ // for these calls is consistent with the matching setXXX() value.\r
+\r
+ // These are the supported setObject conversions from JDBC 3.0 table B5\r
+ // Byte and Short were added to the table in JDBC 4.0.\r
+\r
+ if (x instanceof String) {\r
+ setString(parameterIndex, (String) x);\r
+ return;\r
+ }\r
+\r
+ if (x instanceof Boolean) {\r
+ setBoolean(parameterIndex, ((Boolean) x).booleanValue());\r
+ return;\r
+ }\r
+ if (x instanceof Byte) {\r
+ setByte(parameterIndex, ((Byte) x).byteValue());\r
+ return;\r
+ }\r
+ if (x instanceof Short) {\r
+ setShort(parameterIndex, ((Short) x).shortValue());\r
+ return;\r
+ }\r
+ if (x instanceof Integer) {\r
+ setInt(parameterIndex, ((Integer) x).intValue());\r
+ return;\r
+ }\r
+ if (x instanceof Long) {\r
+ setLong(parameterIndex, ((Long) x).longValue());\r
+ return;\r
+ }\r
+\r
+ if (x instanceof Float) {\r
+ setFloat(parameterIndex, ((Float) x).floatValue());\r
+ return;\r
+ }\r
+ if (x instanceof Double) {\r
+ setDouble(parameterIndex, ((Double) x).doubleValue());\r
+ return;\r
+ }\r
+\r
+ if (x instanceof byte[]) {\r
+ setBytes(parameterIndex, (byte[]) x);\r
+ return;\r
+ }\r
+\r
+ if (x instanceof Date) {\r
+ setDate(parameterIndex, (Date) x);\r
+ return;\r
+ }\r
+ if (x instanceof Time) {\r
+ setTime(parameterIndex, (Time) x);\r
+ return;\r
+ }\r
+ if (x instanceof Timestamp) {\r
+ setTimestamp(parameterIndex, (Timestamp) x);\r
+ return;\r
+ }\r
+\r
+ if (x instanceof Blob) {\r
+ setBlob(parameterIndex, (Blob) x);\r
+ return;\r
+ }\r
+ if (x instanceof Clob) {\r
+ setClob(parameterIndex, (Clob) x);\r
+ return;\r
+ }\r
+\r
+ if (setObjectConvert(parameterIndex, x))\r
+ return;\r
+\r
+ \r
+ throw dataTypeConversion(parameterIndex, x.getClass().getName());\r
+\r
+ }\r
+\r
+ /**\r
+ Allow explict setObject conversions by sub-classes for classes\r
+ not supported by this variant. E.g. BigDecimal\r
+ This top-level implementation always returns false.\r
+\r
+ @return true if the object was set successfully, false if no valid\r
+ conversion exists.\r
+\r
+ @exception SQLException value could not be set.\r
+ */\r
+ boolean setObjectConvert(int parameterIndex, Object x) throws SQLException\r
+ {\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * @see java.sql.Statement#execute\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ public final boolean execute() throws SQLException {\r
+ boolean ret=false;\r
+ try{\r
+ ret = executeStatement(activation, false, false);\r
+ } catch(SQLException sqle) {\r
+ checkStatementValidity(sqle);\r
+ }\r
+ return ret;\r
+ }\r
+ /**\r
+ * Set a parameter to a java.sql.Date value. The driver converts this\r
+ * to a SQL DATE value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException Feature not implemented for now.\r
+ */\r
+ public final void setDate(int parameterIndex, java.sql.Date x, Calendar cal)\r
+ throws SQLException \r
+ {\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a java.sql.Time value. The driver converts this\r
+ * to a SQL TIME value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value\r
+ * @exception SQLException Feature not implemented for now.\r
+ */\r
+ public final void setTime(int parameterIndex, java.sql.Time x, Calendar cal)\r
+ throws SQLException \r
+ {\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);\r
+\r
+ } catch (Throwable t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a parameter to a java.sql.Timestamp value. The driver\r
+ * converts this to a SQL TIMESTAMP value when it sends it to the\r
+ * database.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the parameter value \r
+ * @exception SQLException Feature not implemented for now.\r
+ */\r
+ public final void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)\r
+ throws SQLException \r
+ {\r
+ checkStatus();\r
+ try {\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);\r
+\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * JDBC 2.0\r
+ *\r
+ * Set a BLOB parameter.\r
+ *\r
+ * @param i the first parameter is 1, the second is 2, ...\r
+ * @param x an object representing a BLOB\r
+ */\r
+ public void setBlob (int i, Blob x)\r
+ throws SQLException\r
+ {\r
+ checkBlobConditions(i);\r
+ if (x == null)\r
+ setNull(i, Types.BLOB);\r
+ else\r
+ {\r
+ // Note, x.length() needs to be called before retrieving the\r
+ // stream using x.getBinaryStream() because EmbedBlob.length()\r
+ // will read from the stream and drain some part of the stream \r
+ // Hence the need to declare this local variable - streamLength\r
+ long streamLength = x.length();\r
+ setBinaryStreamInternal(i, x.getBinaryStream(), false,\r
+ streamLength);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Check general (pre)conditions for setClob methods.\r
+ *\r
+ * @param parameterIndex 1-based index of the parameter.\r
+ */\r
+ private final void checkClobConditions(int parameterIndex)\r
+ throws SQLException {\r
+ checkStatus();\r
+ if (getParameterJDBCType(parameterIndex) != Types.CLOB) {\r
+ throw dataTypeConversion(parameterIndex, "java.sql.Clob");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * JDBC 2.0\r
+ *\r
+ * Set a CLOB parameter.\r
+ *\r
+ * @param i the first parameter is 1, the second is 2, ...\r
+ * @param x an object representing a CLOB\r
+ */\r
+ public void setClob (int i, Clob x)\r
+ throws SQLException\r
+ {\r
+ checkClobConditions(i);\r
+ if (x == null)\r
+ setNull(i, Types.CLOB);\r
+ else\r
+ {\r
+ // 1. max number of characters that can be inserted into a clob column\r
+ // is 2Gb-1 which is Integer.MAX_INT.\r
+ // This means that we do not allow any inserts of clobs where\r
+ // clob.length() > Integer.MAX_INT. For now, we cast the x.length()\r
+ // to int as a result. This will work ok for valid clob values that\r
+ // derby supports. If we ever decide to increase these limits for clobs, in that\r
+ // case the cast of x.Length() to int would not be appropriate.\r
+ // 2. Note, x.length() needs to be called before retrieving the\r
+ // stream using x.getCharacterStream() because EmbedClob.length()\r
+ // will read from the stream and drain the stream. \r
+ // Hence the need to declare this local variable - streamLength\r
+ long streamLength = x.length();\r
+\r
+ setCharacterStreamInternal(i, x.getCharacterStream(),\r
+ false, streamLength);\r
+ }\r
+ \r
+ }\r
+\r
+ /**\r
+ * Get the ParameterValueSet from the activation.\r
+ * \r
+ * The caller of this method should be aware that the\r
+ * activation associated with a Statement can change\r
+ * and hence the ParameterValueSet returned by this\r
+ * call should not be hold onto. An example of this\r
+ * can be seen in EmbedCallableStatement.executeStatement\r
+ * where at the beginning of the method, we check the\r
+ * validity of the parameters. But we donot keep the\r
+ * parameters in a local variable to use later. The reason\r
+ * for this is that the next call in the method, \r
+ * super.executeStatement can recompile the statement and \r
+ * create a new activation if the statement plan has been \r
+ * invalidated. To account for this possibility, \r
+ * EmbedCallableStatement.executeStatement makes \r
+ * another call to get the ParameterValueSet before stuffing \r
+ * the output parameter value into the ParameterValueSet\r
+ * object.\r
+ *\r
+ *\r
+ * @return The ParameterValueSet for the activation\r
+ *\r
+ */\r
+ public final ParameterValueSet getParms() {\r
+\r
+ return activation.getParameterValueSet();\r
+ }\r
+\r
+\r
+ /**\r
+ Check the parameterINdex is in range and return the\r
+ array of type descriptors.\r
+\r
+ @exception SQLException parameter is out of range\r
+ */\r
+ protected final DataTypeDescriptor[] getTypes(int parameterIndex)\r
+ throws SQLException {\r
+\r
+ DataTypeDescriptor[] types = preparedStatement.getParameterTypes();\r
+\r
+ if (types == null) {\r
+ throw newSQLException(SQLState.NO_INPUT_PARAMETERS);\r
+ }\r
+\r
+ /* Check that the parameterIndex is in range. */\r
+ if (parameterIndex < 1 ||\r
+ parameterIndex > types.length) {\r
+\r
+ /* This message matches the one used by the DBMS */\r
+ throw newSQLException(SQLState.LANG_INVALID_PARAM_POSITION, \r
+ new Integer(parameterIndex), new Integer(types.length));\r
+ }\r
+ return types;\r
+ }\r
+\r
+ /**\r
+ Get the target JDBC type for a parameter. Will throw exceptions\r
+ if the parameter index is out of range\r
+\r
+ @exception SQLException parameter is out of range\r
+ */\r
+ protected int getParameterJDBCType(int parameterIndex)\r
+ throws SQLException {\r
+\r
+ DataTypeDescriptor[] types = getTypes(parameterIndex);\r
+\r
+ int type = types[parameterIndex -1] == null ? \r
+ Types.OTHER :\r
+ types[parameterIndex - 1].getTypeId().getJDBCTypeId();\r
+\r
+ if (SanityManager.DEBUG) {\r
+ //int pmType = getEmbedParameterSetMetaData().getParameterType(parameterIndex);\r
+ //if (type != pmType) {\r
+ //SanityManager.THROWASSERT("MISMATCH PARAMETER META DATA param " + parameterIndex + " types " + type + " != " + pmType + "\n" + SQLText);\r
+ //}\r
+ }\r
+\r
+ return type;\r
+ }\r
+\r
+ /**\r
+ * Return the SQL type name for the parameter.\r
+ *\r
+ * @param parameterIndex the 1-based index of the parameter\r
+ * @return SQL name of the parameter\r
+ * @throws SQLException if parameter is out of range\r
+ */\r
+ protected final String getParameterSQLType(int parameterIndex)\r
+ throws SQLException {\r
+ DataTypeDescriptor[] pTypes = getTypes(parameterIndex);\r
+ return pTypes[parameterIndex-1].getTypeName();\r
+ }\r
+\r
+ /**\r
+ * Set the scale of a parameter.\r
+ *\r
+ * @param parameterIndex The first parameter is 1, the second is 2, ...\r
+ * @param scale The scale\r
+ * @exception SQLException thrown on failure.\r
+ */\r
+ private void setScale(int parameterIndex, int scale)\r
+ throws SQLException \r
+ {\r
+ checkStatus();\r
+\r
+ if (scale < 0)\r
+ throw newSQLException(SQLState.BAD_SCALE_VALUE, new Integer(scale));\r
+ \r
+ try {\r
+\r
+ ParameterValueSet pvs = getParms();\r
+\r
+ /* JDBC is one-based, DBMS is zero-based */\r
+ DataValueDescriptor value = pvs.getParameter(parameterIndex - 1);\r
+\r
+\r
+ int origvaluelen = value.getLength();\r
+ ((VariableSizeDataValue)\r
+ value).setWidth(VariableSizeDataValue.IGNORE_PRECISION, \r
+ scale, \r
+ false);\r
+\r
+ if (value.getLength() < origvaluelen)\r
+ {\r
+ activation.addWarning(StandardException.newWarning(SQLState.LANG_VALUE_TRUNCATED, value.getString()));\r
+ }\r
+\r
+ } catch (StandardException t) {\r
+ throw EmbedResultSet.noStateChangeException(t);\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Immitate the function in JDBC 3.0\r
+ *\r
+ * Retrieves the number, types and properties of this PreparedStatement\r
+ * object's parameters.\r
+ *\r
+ * @return a EngineParameterMetaData object that contains information about the\r
+ * number, types and properties of this PreparedStatement object's parameters.\r
+ * @exception SQLException if a database access error occurs\r
+ */\r
+ private EngineParameterMetaData getEmbedParameterSetMetaData()\r
+ throws SQLException\r
+ {\r
+ checkExecStatus();\r
+ return new EmbedParameterSetMetaData(\r
+ getParms(), preparedStatement.getParameterTypes());\r
+\r
+ }\r
+ /**\r
+ * JDBC 3.0\r
+ *\r
+ * Sets the designated parameter to the given java.net.URL value. The driver\r
+ * converts this to an SQL DATALINK value when it sends it to the database.\r
+ *\r
+ * @param parameterIndex - the first parameter is 1, the second is 2, ...\r
+ * @param x - the java.net.URL object to be set\r
+ * @exception SQLException Feature not implemented for now.\r
+ */\r
+ public final void setURL(int parameterIndex, java.net.URL x)\r
+ throws SQLException\r
+ {\r
+ throw Util.notImplemented();\r
+ }\r
+\r
+ //\r
+ // methods to be overridden in subimplementations\r
+ // that want to stay within their subimplementation.\r
+ //\r
+ protected EmbedResultSetMetaData newEmbedResultSetMetaData(ResultDescription resultDesc) {\r
+\r
+ return factory.newEmbedResultSetMetaData(resultDesc.getColumnInfo());\r
+ }\r
+\r
+ public String toString() {\r
+\r
+ if (activation != null)\r
+ return activation.getPreparedStatement().getObjectName();\r
+ return super.toString();\r
+ }\r
+\r
+ /*\r
+ **\r
+ */\r
+ public void transferParameters(EmbedPreparedStatement newStatement) throws SQLException {\r
+\r
+ try {\r
+ newStatement.activation.setParameters(getParms(), preparedStatement.getParameterTypes());\r
+ } catch (StandardException se) {\r
+ throw EmbedResultSet.noStateChangeException(se);\r
+ }\r
+ }\r
+\r
+ boolean executeStatement(Activation a,\r
+ boolean executeQuery, boolean executeUpdate)\r
+ throws SQLException {\r
+\r
+ checkExecStatus();\r
+ checkIfInMiddleOfBatch();\r
+ clearResultSets();\r
+ return super.executeStatement(a, executeQuery, executeUpdate);\r
+ }\r
+\r
+ final SQLException dataTypeConversion(int column, String sourceType)\r
+ throws SQLException {\r
+ SQLException se = newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, getEmbedParameterSetMetaData().getParameterTypeName(column),\r
+ sourceType);\r
+ return se;\r
+ }\r
+ /*\r
+ * This method is used to initialize the BrokeredConnectionControl \r
+ * variable with its implementation. This method will be called in the \r
+ * BrokeredConnectionControl class \r
+ *\r
+ * @param control used to call the onStatementClose and \r
+ * onStatementErrorOccurred methods that have logic to \r
+ * raise StatementEvents for the close and error events\r
+ * on the PreparedStatement\r
+ *\r
+ */\r
+ public void setBrokeredConnectionControl(BrokeredConnectionControl control) {\r
+ bcc = control;\r
+ }\r
+ \r
+ /*\r
+ * Method calls onStatementError occurred on the \r
+ * BrokeredConnectionControl class after checking the \r
+ * SQLState of the SQLException thrown.\r
+ *\r
+ * In the case that a XAConnection is involved in the creation of this\r
+ * PreparedStatement for e.g in the following case\r
+ *\r
+ * <code>\r
+ * XAConnection xaconn = xadatasource.getXAConnection();//where xadatasource is an object of XADataSource\r
+ * Connection conn = xaconnection.getConnection();\r
+ * PreparedStatement ps = conn.preparedStatement("values 1");\r
+ * </code>\r
+ *\r
+ * In the above case the PreparedStatement will actually be a \r
+ * BrokeredPreparedStatement40 object. Hence when we call \r
+ * bcc.onStatementClose and pass the PreparedStatement that caused it\r
+ * applicationStatement will be the appropriate choice since it will \r
+ * contain the appropriate instance of PreparedStatement in each case\r
+ *\r
+ */\r
+ \r
+ private void checkStatementValidity(SQLException sqle) throws SQLException {\r
+ /*\r
+ * Check if the exception has occurred because the connection\r
+ * associated with the PreparedStatement has been closed\r
+ */\r
+ if(bcc != null && isClosed()) {\r
+ //call the BrokeredConnectionControl interface method\r
+ //onStatementErrorOccurred\r
+ bcc.onStatementErrorOccurred((java.sql.PreparedStatement)\r
+ applicationStatement,sqle);\r
+ }\r
+ throw sqle;\r
+ }\r
+\r
+ /**\r
+ * Checks whether a data type is supported for\r
+ * <code>setObject(int, Object, int)</code> and\r
+ * <code>setObject(int, Object, int, int)</code>.\r
+ *\r
+ * @param dataType the data type to check\r
+ * @exception SQLException if the type is not supported\r
+ */\r
+ private void checkForSupportedDataType(int dataType) throws SQLException {\r
+\r
+ // JDBC 4.0 javadoc for setObject() says:\r
+ //\r
+ // Throws: (...) SQLFeatureNotSupportedException - if\r
+ // targetSqlType is a ARRAY, BLOB, CLOB, DATALINK,\r
+ // JAVA_OBJECT, NCHAR, NCLOB, NVARCHAR, LONGNVARCHAR, REF,\r
+ // ROWID, SQLXML or STRUCT data type and the JDBC driver does\r
+ // not support this data type\r
+ //\r
+ // Of these types, we only support BLOB, CLOB and\r
+ // (sort of) JAVA_OBJECT.\r
+\r
+ switch (dataType) {\r
+ case Types.ARRAY:\r
+ case JDBC30Translation.DATALINK:\r
+ case JDBC40Translation.NCHAR:\r
+ case JDBC40Translation.NCLOB:\r
+ case JDBC40Translation.NVARCHAR:\r
+ case JDBC40Translation.LONGNVARCHAR:\r
+ case Types.REF:\r
+ case JDBC40Translation.ROWID:\r
+ case JDBC40Translation.SQLXML:\r
+ case Types.STRUCT:\r
+ throw newSQLException(SQLState.DATA_TYPE_NOT_SUPPORTED,\r
+ Util.typeName(dataType));\r
+ }\r
+ }\r
+\r
+ //jdbc 4.0 methods\r
+\r
+ /**\r
+ * Sets the designated parameter to the given input stream.\r
+ * When a very large ASCII value is input to a <code>LONGVARCHAR</code>\r
+ * parameter, it may be more practical to send it via a\r
+ * <code>java.io.InputStream</code>. Data will be read from the stream as\r
+ * needed until end-of-file is reached. The JDBC driver will do any\r
+ * necessary conversion from ASCII to the database char format.\r
+ *\r
+ * <em>Note:</em> This stream object can either be a standard Java stream\r
+ * object or your own subclass that implements the standard interface.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param x the Java input stream that contains the ASCII parameter value\r
+ * @throws SQLException if a database access error occurs or this method is\r
+ * called on a closed <code>PreparedStatement</code>\r
+ */\r
+ public void setAsciiStream(int parameterIndex, InputStream x)\r
+ throws SQLException {\r
+ checkAsciiStreamConditions(parameterIndex);\r
+ java.io.Reader asciiStream = null;\r
+\r
+ if (x != null) {\r
+ // Use ISO-8859-1 and not US-ASCII as JDBC seems to define\r
+ // ASCII as 8 bits. US-ASCII is 7.\r
+ try {\r
+ asciiStream = new java.io.InputStreamReader(x, "ISO-8859-1");\r
+ } catch (java.io.UnsupportedEncodingException uee) {\r
+ throw new SQLException(uee.getMessage());\r
+ }\r
+ }\r
+\r
+ setCharacterStreamInternal(parameterIndex, asciiStream, true, -1);\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to the given <code>Reader</code> object.\r
+ * When a very large UNICODE value is input to a LONGVARCHAR parameter, it\r
+ * may be more practical to send it via a <code>java.io.Reader</code>\r
+ * object. The data will be read from the stream as needed until\r
+ * end-of-file is reached. The JDBC driver will do any necessary conversion\r
+ * from UNICODE to the database char format.\r
+ *\r
+ * <em>Note:</em> This stream object can either be a standard Java stream\r
+ * object or your own subclass that implements the standard interface.\r
+ *\r
+ * Using this lengthless overload is not less effective than using one\r
+ * where the stream length is specified, but since there is no length\r
+ * specified, the exact length check will not be performed.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ * @param reader the <code>java.io.Reader</code> object that contains the\r
+ * Unicode data\r
+ * @throws SQLException if a database access error occurs or this method is\r
+ * called on a closed <code>PreparedStatement</code>\r
+ */\r
+ public void setCharacterStream(int parameterIndex, Reader reader)\r
+ throws SQLException {\r
+ checkCharacterStreamConditions(parameterIndex);\r
+ setCharacterStreamInternal(parameterIndex, reader,\r
+ true, -1);\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to a <code>Reader</code> object.\r
+ * This method differs from the <code>setCharacterStream(int,Reader)</code>\r
+ * method because it informs the driver that the parameter value should be\r
+ * sent to the server as a <code>CLOB</code>. When the\r
+ * <code>setCharacterStream</code> method is used, the driver may have to\r
+ * do extra work to determine whether the parameter data should be sent to\r
+ * the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>.\r
+ *\r
+ * @param parameterIndex index of the first parameter is 1, the second is\r
+ * 2, ...\r
+ * @param reader an object that contains the data to set the parameter\r
+ * value to.\r
+ * @throws SQLException if a database access error occurs, this method is\r
+ * called on a closed PreparedStatementor if parameterIndex does not\r
+ * correspond to a parameter marker in the SQL statement\r
+ */\r
+ public void setClob(int parameterIndex, Reader reader)\r
+ throws SQLException {\r
+ checkClobConditions(parameterIndex);\r
+ setCharacterStreamInternal(parameterIndex, reader, true, -1);\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to a Reader object.\r
+ *\r
+ * @param parameterIndex index of the first parameter is 1, the second is 2, ...\r
+ * @param reader An object that contains the data to set the parameter value to.\r
+ * @param length the number of characters in the parameter data.\r
+ * @throws SQLException if parameterIndex does not correspond to a parameter\r
+ * marker in the SQL statement, or if the length specified is less than zero.\r
+ *\r
+ */\r
+\r
+ \r
+ public void setClob(int parameterIndex, Reader reader, long length)\r
+ throws SQLException{\r
+ checkClobConditions(parameterIndex);\r
+ setCharacterStreamInternal(parameterIndex, reader, false, length);\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to a <code>InputStream</code> object.\r
+ * This method differs from the <code>setBinaryStream(int, InputStream)\r
+ * </code> method because it informs the driver that the parameter value\r
+ * should be sent to the server as a <code>BLOB</code>. When the\r
+ * <code>setBinaryStream</code> method is used, the driver may have to do\r
+ * extra work to determine whether the parameter data should be sent to the\r
+ * server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>\r
+ *\r
+ * @param parameterIndex index of the first parameter is 1, the second is\r
+ * 2, ...\r
+ * @param inputStream an object that contains the data to set the parameter\r
+ * value to.\r
+ * @throws SQLException if a database access error occurs, this method is\r
+ * called on a closed <code>PreparedStatement</code> or if\r
+ * <code>parameterIndex</code> does not correspond to a parameter\r
+ * marker in the SQL statement\r
+ */\r
+ public void setBlob(int parameterIndex, InputStream inputStream)\r
+ throws SQLException {\r
+ checkBlobConditions(parameterIndex);\r
+ setBinaryStreamInternal(parameterIndex, inputStream, true, -1);\r
+ }\r
+\r
+ /**\r
+ * Sets the designated parameter to a InputStream object.\r
+ *\r
+ * @param parameterIndex index of the first parameter is 1,\r
+ * the second is 2, ...\r
+ * @param inputStream An object that contains the data to set the parameter\r
+ * value to.\r
+ * @param length the number of bytes in the parameter data.\r
+ * @throws SQLException if parameterIndex does not correspond\r
+ * to a parameter marker in the SQL statement, if the length specified\r
+ * is less than zero or if the number of bytes in the inputstream does not match\r
+ * the specfied length.\r
+ */\r
+\r
+ \r
+ public void setBlob(int parameterIndex, InputStream inputStream, long length)\r
+ throws SQLException{\r
+ checkBlobConditions(parameterIndex);\r
+ setBinaryStreamInternal(parameterIndex, inputStream, false, length);\r
+ }\r
+\r
+ /**\r
+ * Check general (pre)conditions for setBlob methods.\r
+ *\r
+ * @param parameterIndex 1-based index of the parameter.\r
+ */\r
+ private final void checkBlobConditions(int parameterIndex)\r
+ throws SQLException {\r
+ checkStatus();\r
+ if (getParameterJDBCType(parameterIndex) != Types.BLOB) {\r
+ throw dataTypeConversion(parameterIndex, "java.sql.Blob");\r
+ }\r
+ }\r
+}\r