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