0001: /* Copyright (c) 2001-2005, The HSQL Development Group
0002: * All rights reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * Redistributions of source code must retain the above copyright notice, this
0008: * list of conditions and the following disclaimer.
0009: *
0010: * Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * Neither the name of the HSQL Development Group nor the names of its
0015: * contributors may be used to endorse or promote products derived from this
0016: * software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
0022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: */
0030:
0031: package org.hsqldb.jdbc;
0032:
0033: import java.io.IOException;
0034: import java.io.Serializable;
0035: import java.math.BigDecimal;
0036: import java.sql.Date;
0037: import java.sql.PreparedStatement;
0038: import java.sql.ResultSet;
0039: import java.sql.ResultSetMetaData;
0040: import java.sql.SQLException;
0041: import java.sql.Time;
0042: import java.sql.Timestamp;
0043: import java.util.Calendar;
0044:
0045: //#ifdef JAVA2
0046: import java.sql.Array;
0047: import java.sql.Blob;
0048: import java.sql.Clob;
0049: import java.sql.Ref;
0050:
0051: //#endif JAVA2
0052: //#ifdef JDBC3
0053: import java.sql.ParameterMetaData;
0054:
0055: //#endif JDBC3
0056: import org.hsqldb.Column;
0057: import org.hsqldb.HsqlDateTime;
0058: import org.hsqldb.HsqlException;
0059: import org.hsqldb.Result;
0060: import org.hsqldb.ResultConstants;
0061: import org.hsqldb.Trace;
0062: import org.hsqldb.Types;
0063: import org.hsqldb.lib.ArrayUtil;
0064: import org.hsqldb.lib.HsqlByteArrayOutputStream;
0065: import org.hsqldb.lib.Iterator;
0066: import org.hsqldb.lib.StringConverter;
0067: import org.hsqldb.types.Binary;
0068: import org.hsqldb.types.JavaObject;
0069:
0070: // fredt@users 20020320 - patch 1.7.0 - JDBC 2 support and error trapping
0071: // JDBC 2 methods can now be called from jdk 1.1.x - see javadoc comments
0072: // boucherb@users 20020509 - added "throws SQLException" to all methods where
0073: // it was missing here but specified in the java.sql.PreparedStatement and
0074: // java.sqlCallableStatement interfaces, updated generic documentation to
0075: // JDK 1.4, and added JDBC3 methods and docs
0076: // boucherb@users and fredt@users 20020409/20020505 extensive review and update
0077: // of docs and behaviour to comply with previous and latest java.sql specification
0078: // fredt@users 20030620 - patch 1.7.2 - rewritten to support real prepared statements
0079: // boucherb@users 20030801 - patch 1.7.2 - support for batch execution
0080: // boucherb@users 20030801 - patch 1.7.2 - support for getMetaData and getParameterMetadata
0081: // boucherb@users 20030801 - patch 1.7.2 - updated some setXXX methods
0082: // boucherb@users 200403/4xx - doc 1.7.2 - javadoc updates toward 1.7.2 final
0083: // boucherb@users 200403/4xx - patch 1.7.2 - eliminate eager buffer allocation from setXXXStream/Blob/Clob
0084: // fredt@users 20060215 - patch 1.8.0 - check for unset parameters
0085:
0086: /**
0087: * <!-- start generic documentation -->
0088: *
0089: * An object that represents a precompiled SQL statement. <p>
0090: *
0091: * An SQL statement is precompiled and stored in a
0092: * <code>PreparedStatement</code> object. This object can then be used to
0093: * efficiently execute this statement multiple times.
0094: *
0095: * <P><B>Note:</B> The setter methods (<code>setShort</code>,
0096: * <code>setString</code>, and so on) for setting IN parameter values
0097: * must specify types that are compatible with the defined SQL type of
0098: * the input parameter. For instance, if the IN parameter has SQL type
0099: * <code>INTEGER</code>, then the method <code>setInt</code> should be
0100: * used. <p>
0101: *
0102: * If arbitrary parameter type conversions are required, the method
0103: * <code>setObject</code> should be used with a target SQL type.
0104: * <P>
0105: * In the following example of setting a parameter, <code>con</code>
0106: * represents an active connection:
0107: * <PRE>
0108: * PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
0109: * SET SALARY = ? WHERE ID = ?");
0110: * pstmt.setBigDecimal(1, 153833.00)
0111: * pstmt.setInt(2, 110592)
0112: * </PRE> <p>
0113: * <!-- end generic documentation -->
0114: * <!-- start Release-specific documentation -->
0115: * <div class="ReleaseSpecificDocumentation">
0116: * <h3>HSQLDB-Specific Information:</h3> <p>
0117: *
0118: * Starting with HSQLDB 1.7.2, jdbcPreparedStatement objects are backed by
0119: * a true compiled parameteric representation. Hence, there are now significant
0120: * performance gains to be had by using a jdbcPreparedStatement object in
0121: * preference to a jdbcStatement object, if a short-running SQL statement is
0122: * to be executed more than a small number of times. <p>
0123: *
0124: * When it can be otherwise avoided, it is to be considered poor
0125: * practice to fully prepare (construct), parameterize, execute, fetch and
0126: * close a jdbcPreparedStatement object for each execution cycle. Indeed, under
0127: * HSQLDB 1.8.0, this practice is likely to be noticably <em>less</em>
0128: * performant for short-running statements than the equivalent process using
0129: * jdbcStatement objects, albeit far more convenient, less error prone and
0130: * certainly much less resource-intensive, especially when large binary and
0131: * character values are involved, due to the optimized parameterization
0132: * facility. <p>
0133: *
0134: * Instead, when developing an application that is not totally oriented toward
0135: * the execution of ad hoc SQL, it is recommended to expend some effort toward
0136: * identifing the SQL statements that are good candidates for regular reuse and
0137: * adapting the structure of the application accordingly. Often, this is done
0138: * by recording the text of candidate SQL statements in an application resource
0139: * object (which has the nice side-benefit of isolating and hiding differences
0140: * in SQL dialects across different drivers) and caching for possible reuse the
0141: * PreparedStatement objects derived from the recorded text. <p>
0142: *
0143: * <b>Multi thread use:</b> <p>
0144: *
0145: * A PreparedStatement object is stateful and should not normally be shared
0146: * by multiple threads. If it has to be shared, the calls to set the
0147: * parameters, calls to add batch statements, the execute call and any
0148: * post-execute calls should be made within a block synchronized on the
0149: * PreparedStatement Object.<p>
0150: *
0151: * <b>JRE 1.1.x Notes:</b> <p>
0152: *
0153: * In general, JDBC 2 support requires Java 1.2 and above, and JDBC3 requires
0154: * Java 1.4 and above. In HSQLDB, support for methods introduced in different
0155: * versions of JDBC depends on the JDK version used for compiling and building
0156: * HSQLDB.<p>
0157: *
0158: * Since 1.7.0, it is possible to build the product so that
0159: * all JDBC 2 methods can be called while executing under the version 1.1.x
0160: * <em>Java Runtime Environment</em><sup><font size="-2">TM</font></sup>.
0161: * However, in addition to requiring explicit casts to the org.hsqldb.jdbcXXX
0162: * interface implementations, some of these method calls require
0163: * <code>int</code> values that are defined only in the JDBC 2 or greater
0164: * version of
0165: * <a href="http://java.sun.com/j2se/1.4/docs/api/java/sql/ResultSet.html">
0166: * <code>ResultSet</code></a> interface. For this reason, when the
0167: * product is compiled under JDK 1.1.x, these values are defined in
0168: * {@link jdbcResultSet jdbcResultSet}.<p>
0169: *
0170: * In a JRE 1.1.x environment, calling JDBC 2 methods that take or return the
0171: * JDBC2-only <code>ResultSet</code> values can be achieved by referring
0172: * to them in parameter specifications and return value comparisons,
0173: * respectively, as follows: <p>
0174: *
0175: * <pre class="JavaCodeExample">
0176: * jdbcResultSet.FETCH_FORWARD
0177: * jdbcResultSet.TYPE_FORWARD_ONLY
0178: * jdbcResultSet.TYPE_SCROLL_INSENSITIVE
0179: * jdbcResultSet.CONCUR_READ_ONLY
0180: * // etc.
0181: * </pre>
0182: *
0183: * However, please note that code written in such a manner will not be
0184: * compatible for use with other JDBC 2 drivers, since they expect and use
0185: * <code>ResultSet</code>, rather than <code>jdbcResultSet</code>. Also
0186: * note, this feature is offered solely as a convenience to developers
0187: * who must work under JDK 1.1.x due to operating constraints, yet wish to
0188: * use some of the more advanced features available under the JDBC 2
0189: * specification.<p>
0190: *
0191: * (fredt@users)<br>
0192: * (boucherb@users)
0193: * </div>
0194: * <!-- end Release-specific documentation -->
0195: *
0196: * @author boucherb@users
0197: * @author fredt@users
0198: * @version 1.8.0
0199: * @see jdbcConnection#prepareStatement
0200: * @see jdbcResultSet
0201: */
0202: public class jdbcPreparedStatement extends jdbcStatement implements
0203: PreparedStatement {
0204:
0205: /** The parameter values for the next non-batch execution. */
0206: protected Object[] parameterValues;
0207:
0208: /** Flags for bound variables. */
0209: protected boolean[] parameterSet;
0210:
0211: /** Flags for bound stream variables. */
0212: protected boolean[] parameterStream;
0213:
0214: /** The SQL types of the parameters. */
0215: protected int[] parameterTypes;
0216:
0217: /** The (IN, IN OUT, or OUT) modes of parameters */
0218: protected int[] parameterModes;
0219:
0220: /** Lengths for streams. */
0221: protected int[] streamLengths;
0222:
0223: /** Has a stream or CLOB / BLOB parameter value. */
0224: protected boolean hasStreams;
0225:
0226: /**
0227: * Description of result set metadata. <p>
0228: */
0229: protected Result rsmdDescriptor;
0230:
0231: /** Description of parameter metadata. */
0232: protected Result pmdDescriptor;
0233:
0234: /** This object's one and one ResultSetMetaData object. */
0235: protected jdbcResultSetMetaData rsmd;
0236:
0237: // NOTE: pmd is declared as Object to avoid yet another #ifdef.
0238:
0239: /** This object's one and only ParameterMetaData object. */
0240: protected Object pmd;
0241:
0242: /** The SQL character sequence that this object represents. */
0243: protected String sql;
0244:
0245: /**
0246: * The id with which this object's corresponding
0247: * {@link org.hsqldb.CompiledStatement CompiledStatement}
0248: * object is registered in the engine's
0249: * {@link org.hsqldb.CompiledStatementManager CompiledStatementManager}
0250: * object.
0251: */
0252: protected int statementID;
0253:
0254: /**
0255: * Whether this statement generates only a single row update count in
0256: * response to execution.
0257: */
0258: protected boolean isRowCount;
0259:
0260: // fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
0261: // fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
0262: //
0263: // changes by fredt
0264: // SimpleDateFormat objects moved out of methods to improve performance
0265: // this is safe because only one thread at a time should access a
0266: // PreparedStatement object until it has finished executing the statement
0267: // fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
0268: // minor changes by fredt
0269:
0270: /**
0271: * <!-- start generic documentation -->
0272: * Sets escape processing on or off. <p>
0273: * <!-- end generic documentation -->
0274: *
0275: * <!-- start release-specific documentation -->
0276: * <div class="ReleaseSpecificDocumentation">
0277: * <h3>HSQLDB-Specific Information:</h3> <p>
0278: *
0279: * Since 1.7.0, the implementation follows the standard
0280: * behaviour by overriding the same method in jdbcStatement
0281: * class. <p>
0282: *
0283: * In other words, calling this method has no effect.
0284: * </div>
0285: * <!-- end release-specific documentation -->
0286: *
0287: * @param enable <code>true</code> to enable escape processing;
0288: * <code>false</code> to disable it
0289: * @exception SQLException if a database access error occurs
0290: */
0291: public void setEscapeProcessing(boolean enable) throws SQLException {
0292: checkClosed();
0293: }
0294:
0295: /**
0296: * <!-- start generic documentation -->
0297: * Executes the SQL statement in this <code>PreparedStatement</code>
0298: * object, which may be any kind of SQL statement.
0299: * Some prepared statements return multiple results; the
0300: * <code>execute</code> method handles these complex statements as well
0301: * as the simpler form of statements handled by the methods
0302: * <code>executeQuery</code>and <code>executeUpdate</code>. <p>
0303: *
0304: * The <code>execute</code> method returns a <code>boolean</code> to
0305: * indicate the form of the first result. You must call either the method
0306: * <code>getResultSet</code> or <code>getUpdateCount</code>
0307: * to retrieve the result; you must call <code>getMoreResults</code> to
0308: * move to any subsequent result(s). <p>
0309: * <!-- end generic documentation -->
0310: *
0311: * <!-- start release-specific documentation -->
0312: * <div class="ReleaseSpecificDocumentation">
0313: * <h3>HSQLDB-Specific Information:</h3> <p>
0314: *
0315: * Including 1.8.0, prepared statements do not generate
0316: * multiple fetchable results. <p>
0317: *
0318: * In future versions, it will be possible that statements
0319: * generate multiple fetchable results under certain conditions.
0320: * </div>
0321: *
0322: * @return <code>true</code> if the first result is a <code>ResultSet</code>
0323: * object; <code>false</code> if the first result is an update
0324: * count or there is no result
0325: * @exception SQLException if a database access error occurs or an argument
0326: * is supplied to this method
0327: * @see jdbcStatement#execute
0328: * @see jdbcStatement#getResultSet
0329: * @see jdbcStatement#getUpdateCount
0330: * @see jdbcStatement#getMoreResults
0331: */
0332: public boolean execute() throws SQLException {
0333:
0334: checkClosed();
0335: connection.clearWarningsNoCheck();
0336:
0337: resultIn = null;
0338:
0339: try {
0340: resultOut.setMaxRows(maxRows);
0341: resultOut.setParameterData(parameterValues);
0342:
0343: resultIn = connection.sessionProxy.execute(resultOut);
0344: } catch (HsqlException e) {
0345: throw Util.sqlException(e);
0346: }
0347:
0348: if (resultIn.isError()) {
0349: Util.throwError(resultIn);
0350: }
0351:
0352: return resultIn.isData();
0353: }
0354:
0355: /**
0356: * <!-- start generic documentation -->
0357: * Executes the SQL query in this <code>PreparedStatement</code> object
0358: * and returns the <code>ResultSet</code> object generated by the query.<p>
0359: * <!-- end generic documentation -->
0360: *
0361: * @return a <code>ResultSet</code> object that contains the data produced
0362: * by the query; never <code>null</code>
0363: * @exception SQLException if a database access error occurs or the SQL
0364: * statement does not return a <code>ResultSet</code> object
0365: */
0366: public ResultSet executeQuery() throws SQLException {
0367:
0368: checkClosed();
0369: connection.clearWarningsNoCheck();
0370: checkIsRowCount(false);
0371: checkParametersSet();
0372:
0373: resultIn = null;
0374:
0375: try {
0376: resultOut.setMaxRows(maxRows);
0377: resultOut.setParameterData(parameterValues);
0378:
0379: resultIn = connection.sessionProxy.execute(resultOut);
0380: } catch (HsqlException e) {
0381: throw Util.sqlException(e);
0382: }
0383:
0384: if (resultIn.isError()) {
0385: Util.throwError(resultIn);
0386: } else if (!resultIn.isData()) {
0387: String msg = "Expected but did not recieve a result set";
0388:
0389: throw Util.sqlException(Trace.UNEXPECTED_EXCEPTION, msg);
0390: }
0391:
0392: return new jdbcResultSet(this , resultIn,
0393: connection.connProperties, connection.isNetConn);
0394: }
0395:
0396: /**
0397: * <!-- start generic documentation -->
0398: * Executes the SQL statement in this <code>PreparedStatement</code>
0399: * object, which must be an SQL <code>INSERT</code>,
0400: * <code>UPDATE</code> or <code>DELETE</code> statement; or an SQL
0401: * statement that returns nothing, such as a DDL statement.<p>
0402: * <!-- end generic documentation -->
0403: *
0404: * @return either (1) the row count for <code>INSERT</code>,
0405: * <code>UPDATE</code>, or <code>DELETE</code>
0406: * statements or (2) 0 for SQL statements that
0407: * return nothing
0408: * @exception SQLException if a database access error occurs or the SQL
0409: * statement returns a <code>ResultSet</code> object
0410: */
0411: public int executeUpdate() throws SQLException {
0412:
0413: checkClosed();
0414: connection.clearWarningsNoCheck();
0415: checkIsRowCount(true);
0416: checkParametersSet();
0417:
0418: resultIn = null;
0419:
0420: try {
0421: resultOut.setParameterData(parameterValues);
0422:
0423: resultIn = connection.sessionProxy.execute(resultOut);
0424: } catch (HsqlException e) {
0425: throw Util.sqlException(e);
0426: }
0427:
0428: if (resultIn.isError()) {
0429: Util.throwError(resultIn);
0430: } else if (resultIn.mode != ResultConstants.UPDATECOUNT) {
0431: String msg = "Expected but did not recieve a row update count";
0432:
0433: throw Util.sqlException(Trace.UNEXPECTED_EXCEPTION, msg);
0434: }
0435:
0436: return resultIn.getUpdateCount();
0437: }
0438:
0439: /**
0440: * <!-- start generic documentation -->
0441: * Submits a batch of commands to the database for execution and
0442: * if all commands execute successfully, returns an array of update counts.
0443: * The <code>int</code> elements of the array that is returned are ordered
0444: * to correspond to the commands in the batch, which are ordered
0445: * according to the order in which they were added to the batch.
0446: * The elements in the array returned by the method <code>executeBatch</code>
0447: * may be one of the following:
0448: * <OL>
0449: * <LI>A number greater than or equal to zero -- indicates that the
0450: * command was processed successfully and is an update count giving the
0451: * number of rows in the database that were affected by the command's
0452: * execution
0453: * <LI>A value of <code>SUCCESS_NO_INFO</code> -- indicates that the command was
0454: * processed successfully but that the number of rows affected is
0455: * unknown
0456: * <P>
0457: * If one of the commands in a batch update fails to execute properly,
0458: * this method throws a <code>BatchUpdateException</code>, and a JDBC
0459: * driver may or may not continue to process the remaining commands in
0460: * the batch. However, the driver's behavior must be consistent with a
0461: * particular DBMS, either always continuing to process commands or never
0462: * continuing to process commands. If the driver continues processing
0463: * after a failure, the array returned by the method
0464: * <code>BatchUpdateException.getUpdateCounts</code>
0465: * will contain as many elements as there are commands in the batch, and
0466: * at least one of the elements will be the following:
0467: * <P>
0468: * <LI>A value of <code>EXECUTE_FAILED</code> -- indicates that the command failed
0469: * to execute successfully and occurs only if a driver continues to
0470: * process commands after a command fails
0471: * </OL>
0472: * <P>
0473: * A driver is not required to implement this method.
0474: * The possible implementations and return values have been modified in
0475: * the Java 2 SDK, Standard Edition, version 1.3 to
0476: * accommodate the option of continuing to proccess commands in a batch
0477: * update after a <code>BatchUpdateException</code> obejct has been thrown. <p>
0478: * <!-- end generic documentation -->
0479: *
0480: * <!-- start release-specific documentation -->
0481: * <div class="ReleaseSpecificDocumentation">
0482: * <h3>HSQLDB-Specific Information:</h3> <p>
0483: *
0484: * Starting with HSQLDB 1.7.2, this feature is supported. <p>
0485: *
0486: * HSQLDB stops execution of commands in a batch when one of the commands
0487: * results in an exception. The size of the returned array equals the
0488: * number of commands that were executed successfully.<p>
0489: *
0490: * When the product is built under the JAVA1 target, an exception
0491: * is never thrown and it is the responsibility of the client software to
0492: * check the size of the returned update count array to determine if any
0493: * batch items failed. To build and run under the JAVA2 target, JDK/JRE
0494: * 1.3 or higher must be used.
0495: * </div>
0496: * <!-- end release-specific documentation -->
0497: *
0498: * @return an array of update counts containing one element for each
0499: * command in the batch. The elements of the array are ordered according
0500: * to the order in which commands were added to the batch.
0501: * @exception SQLException if a database access error occurs or the
0502: * driver does not support batch statements. Throws
0503: * {@link java.sql.BatchUpdateException}
0504: * (a subclass of <code>java.sql.SQLException</code>) if one of the commands
0505: * sent to the database fails to execute properly or attempts to return a
0506: * result set.
0507: * @since JDK 1.3 (JDK 1.1.x developers: read the new overview
0508: * for jdbcStatement)
0509: */
0510: public int[] executeBatch() throws SQLException {
0511:
0512: if (batchResultOut == null) {
0513: batchResultOut = new Result(ResultConstants.BATCHEXECUTE,
0514: parameterTypes, statementID);
0515: }
0516:
0517: return super .executeBatch();
0518: }
0519:
0520: /**
0521: * <!-- start generic documentation -->
0522: * Sets the designated parameter to SQL <code>NULL</code>. <p>
0523: *
0524: * <B>Note:</B> You must specify the parameter's SQL type.<p>
0525: * <!-- end generic documentation -->
0526: *
0527: * <!-- start release-specific documentation -->
0528: * <div class="ReleaseSpecificDocumentation">
0529: * <h3>HSQLDB-Specific Information:</h3> <p>
0530: *
0531: * HSQLDB ignores the sqlType argument.
0532: * </div>
0533: * <!-- end release-specific documentation -->
0534: *
0535: * @param paramIndex the first parameter is 1, the second is 2, ...
0536: * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
0537: * @exception SQLException if a database access error occurs
0538: */
0539: public void setNull(int paramIndex, int sqlType)
0540: throws SQLException {
0541: setParameter(paramIndex, null);
0542: }
0543:
0544: /**
0545: * <!-- start generic documentation -->
0546: * Sets the designated parameter to the given Java <code>boolean</code>
0547: * value. The driver converts this to an SQL <code>BIT</code> value
0548: * when it sends it to the database.<p>
0549: * <!-- end generic documentation -->
0550: *
0551: * <!-- start release-specific documentation -->
0552: * <div class="ReleaseSpecificDocumentation">
0553: * <h3>HSQLDB-Specific Information:</h3> <p>
0554: *
0555: * Since 1.7.2, HSQLDB uses the BOOLEAN type instead of BIT, as
0556: * per SQL 200n (SQL 3).
0557: * </div>
0558: * <!-- end release-specific documentation -->
0559: *
0560: * @param parameterIndex the first parameter is 1, the second is 2, ...
0561: * @param x the parameter value
0562: * @exception SQLException if a database access error occurs
0563: */
0564: public void setBoolean(int parameterIndex, boolean x)
0565: throws SQLException {
0566:
0567: Boolean b = x ? Boolean.TRUE : Boolean.FALSE;
0568:
0569: setParameter(parameterIndex, b);
0570: }
0571:
0572: /**
0573: * <!-- start generic documentation -->
0574: * Sets the designated parameter to the given Java <code>byte</code> value.
0575: * The driver converts this to an SQL <code>TINYINT</code> value when
0576: * it sends it to the database.<p>
0577: * <!-- end generic documentation -->
0578: *
0579: * @param parameterIndex the first parameter is 1, the second is 2, ...
0580: * @param x the parameter value
0581: * @exception SQLException if a database access error occurs
0582: */
0583: public void setByte(int parameterIndex, byte x) throws SQLException {
0584: setIntParameter(parameterIndex, x);
0585: }
0586:
0587: /**
0588: * <!-- start generic documentation -->
0589: * Sets the designated parameter to the given Java <code>short</code>
0590: * value. The driver converts this to an SQL <code>SMALLINT</code>
0591: * value when it sends it to the database.<p>
0592: * <!-- end generic documentation -->
0593: *
0594: * @param parameterIndex the first parameter is 1, the second is 2, ...
0595: * @param x the parameter value
0596: * @exception SQLException if a database access error occurs
0597: */
0598: public void setShort(int parameterIndex, short x)
0599: throws SQLException {
0600: setIntParameter(parameterIndex, x);
0601: }
0602:
0603: /**
0604: * <!-- start generic documentation -->
0605: * Sets the designated parameter to the given Java <code>int</code> value.
0606: * The driver converts this to an SQL <code>INTEGER</code> value when
0607: * it sends it to the database.<p>
0608: * <!-- end generic documentation -->
0609: *
0610: * @param parameterIndex the first parameter is 1, the second is 2, ...
0611: * @param x the parameter value
0612: * @exception SQLException if a database access error occurs
0613: */
0614: public void setInt(int parameterIndex, int x) throws SQLException {
0615: setIntParameter(parameterIndex, x);
0616: }
0617:
0618: /**
0619: * <!-- start generic documentation -->
0620: * Sets the designated parameter to the given Java <code>long</code> value.
0621: * The driver converts this to an SQL <code>BIGINT</code> value when
0622: * it sends it to the database.<p>
0623: * <!-- end generic documentation -->
0624: *
0625: * @param parameterIndex the first parameter is 1, the second is 2, ...
0626: * @param x the parameter value
0627: * @exception SQLException if a database access error occurs
0628: */
0629: public void setLong(int parameterIndex, long x) throws SQLException {
0630: setLongParameter(parameterIndex, x);
0631: }
0632:
0633: /**
0634: * <!-- start generic documentation -->
0635: * Sets the designated parameter to the given Java <code>float</code> value.
0636: * The driver converts this to an SQL <code>FLOAT</code> value when
0637: * it sends it to the database.<p>
0638: * <!-- end generic documentation -->
0639: *
0640: * <!-- start release-specific documentation -->
0641: * <div class="ReleaseSpecificDocumentation">
0642: * <h3>HSQLDB-Specific Information:</h3> <p>
0643: *
0644: * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
0645: * and NaN <code>float</code> values consistent with the Java Language
0646: * Specification; these <em>special</em> values are now correctly stored
0647: * to and retrieved from the database.
0648: * </div>
0649: * <!-- start release-specific documentation -->
0650: *
0651: * @param parameterIndex the first parameter is 1, the second is 2, ...
0652: * @param x the parameter value
0653: * @exception SQLException if a database access error occurs
0654: */
0655: public void setFloat(int parameterIndex, float x)
0656: throws SQLException {
0657: setDouble(parameterIndex, (double) x);
0658: }
0659:
0660: /**
0661: * <!-- start generic documentation -->
0662: * Sets the designated parameter to the given Java <code>double</code> value.
0663: * The driver converts this to an SQL <code>DOUBLE</code> value when it
0664: * sends it to the database.<p>
0665: * <!-- end generic documentation -->
0666: *
0667: * <!-- start release-specific documentation -->
0668: * <div class="ReleaseSpecificDocumentation">
0669: * <h3>HSQLDB-Specific Information:</h3> <p>
0670: *
0671: * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
0672: * and NaN <code>double</code> values consistent with the Java Language
0673: * Specification; these <em>special</em> values are now correctly stored
0674: * to and retrieved from the database.
0675: * </div>
0676: * <!-- start release-specific documentation -->
0677: *
0678: * @param parameterIndex the first parameter is 1, the second is 2, ...
0679: * @param x the parameter value
0680: * @exception SQLException if a database access error occurs
0681: */
0682: public void setDouble(int parameterIndex, double x)
0683: throws SQLException {
0684:
0685: Double d = new Double(x);
0686:
0687: setParameter(parameterIndex, d);
0688: }
0689:
0690: /**
0691: * <!-- start generic documentation -->
0692: * Sets the designated parameter to the given
0693: * <code>java.math.BigDecimal</code> value.
0694: * The driver converts this to an SQL <code>NUMERIC</code> value when
0695: * it sends it to the database.<p>
0696: * <!-- end generic documentation -->
0697: *
0698: * @param parameterIndex the first parameter is 1, the second is 2, ...
0699: * @param x the parameter value
0700: * @exception SQLException if a database access error occurs
0701: */
0702: public void setBigDecimal(int parameterIndex, BigDecimal x)
0703: throws SQLException {
0704: setParameter(parameterIndex, x);
0705: }
0706:
0707: /**
0708: * <!-- start generic documentation -->
0709: * Sets the designated parameter to the given Java <code>String</code> value.
0710: * The driver converts this
0711: * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
0712: * (depending on the argument's
0713: * size relative to the driver's limits on <code>VARCHAR</code> values)
0714: * when it sends it to the database.<p>
0715: * <!-- end generic documentation -->
0716: *
0717: * <!-- start release-specific documentation -->
0718: * <div class="ReleaseSpecificDocumentation">
0719: * <h3>HSQLDB-Specific Information:</h3> <p>
0720: *
0721: * Including 1.7.2, HSQLDB stores all XXXCHAR values as java.lang.String
0722: * objects; there is no appreciable difference between
0723: * CHAR, VARCHAR and LONGVARCHAR.
0724: * </div>
0725: * <!-- start release-specific documentation -->
0726: *
0727: * @param parameterIndex the first parameter is 1, the second is 2, ...
0728: * @param x the parameter value
0729: * @exception SQLException if a database access error occurs
0730: */
0731: public void setString(int parameterIndex, String x)
0732: throws SQLException {
0733: setParameter(parameterIndex, x);
0734: }
0735:
0736: /**
0737: * <!-- start generic documentation -->
0738: * Sets the designated parameter to the given Java array of bytes.
0739: * The driver converts this to an SQL <code>VARBINARY</code> or
0740: * <code>LONGVARBINARY</code> (depending on the argument's size relative
0741: * to the driver's limits on <code>VARBINARY</code> values) when it
0742: * sends it to the database.<p>
0743: * <!-- end generic documentation -->
0744: *
0745: * <!-- start release-specific documentation -->
0746: * <div class="ReleaseSpecificDocumentation">
0747: * <h3>HSQLDB-Specific Information:</h3> <p>
0748: *
0749: * Including 1.7.2, HSQLDB stores all XXXBINARY values the same way; there
0750: * is no appreciable difference between BINARY, VARBINARY and
0751: * LONGVARBINARY.
0752: * </div>
0753: * <!-- start release-specific documentation -->
0754: *
0755: * @param paramIndex the first parameter is 1, the second is 2, ...
0756: * @param x the parameter value
0757: * @exception SQLException if a database access error occurs
0758: */
0759: public void setBytes(int paramIndex, byte[] x) throws SQLException {
0760: setParameter(paramIndex, x);
0761: }
0762:
0763: /**
0764: * <!-- start generic documentation -->
0765: * Sets the designated parameter to the given
0766: * <code>java.sql.Date</code> value. The driver converts this
0767: * to an SQL <code>DATE</code> value when it sends it to the database.<p>
0768: * <!-- end generic documentation -->
0769: *
0770: * @param parameterIndex the first parameter is 1, the second is 2, ...
0771: * @param x the parameter value
0772: * @exception SQLException if a database access error occurs
0773: */
0774: public void setDate(int parameterIndex, Date x) throws SQLException {
0775: setParameter(parameterIndex, x);
0776: }
0777:
0778: /**
0779: * <!-- start generic documentation -->
0780: * Sets the designated parameter to the given <code>java.sql.Time</code>
0781: * value. The driver converts this to an SQL <code>TIME</code> value when it
0782: * sends it to the database.<p>
0783: * <!-- end generic documentation -->
0784: *
0785: * @param parameterIndex the first parameter is 1, the second is 2, ...
0786: * @param x the parameter value
0787: * @exception SQLException if a database access error occurs
0788: */
0789: public void setTime(int parameterIndex, Time x) throws SQLException {
0790: setParameter(parameterIndex, x);
0791: }
0792:
0793: /**
0794: * <!-- start generic documentation -->
0795: * Sets the designated parameter to the given
0796: * <code>java.sql.Timestamp</code> value. The driver converts this to
0797: * an SQL <code>TIMESTAMP</code> value when it sends it to the
0798: * database.<p>
0799: * <!-- end generic documentation -->
0800: *
0801: * @param parameterIndex the first parameter is 1, the second is 2, ...
0802: * @param x the parameter value
0803: * @exception SQLException if a database access error occurs
0804: */
0805: public void setTimestamp(int parameterIndex, Timestamp x)
0806: throws SQLException {
0807: setParameter(parameterIndex, x);
0808: }
0809:
0810: /**
0811: * <!-- start generic documentation -->
0812: * Sets the designated parameter to the given input stream, which will have
0813: * the specified number of bytes.
0814: * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
0815: * parameter, it may be more practical to send it via a
0816: * <code>java.io.InputStream</code>. Data will be read from the stream
0817: * as needed until end-of-file is reached. The JDBC driver will
0818: * do any necessary conversion from ASCII to the database char format. <p>
0819: *
0820: * <b>Note:</b> This stream object can either be a standard
0821: * Java stream object or your own subclass that implements the
0822: * standard interface.<p>
0823: * <!-- end generic documentation -->
0824: * <!-- start release-specific documentation -->
0825: * <div class="ReleaseSpecificDocumentation">
0826: * <h3>HSQLDB-Specific Information:</h3> <p>
0827: *
0828: * This method uses the default platform character encoding to convert bytes
0829: * from the stream into the characters of a String. In the future this is
0830: * likely to change to always treat the stream as ASCII.<p>
0831: *
0832: * Before HSQLDB 1.7.0, <code>setAsciiStream</code> and
0833: * <code>setUnicodeStream</code> were identical.
0834: * </div>
0835: * <!-- end release-specific documentation -->
0836: *
0837: * @param parameterIndex the first parameter is 1, the second is 2, ...
0838: * @param x the Java input stream that contains the ASCII parameter value
0839: * @param length the number of bytes in the stream
0840: * @exception SQLException if a database access error occurs
0841: */
0842: public void setAsciiStream(int parameterIndex,
0843: java.io.InputStream x, int length) throws SQLException {
0844:
0845: checkSetParameterIndex(parameterIndex, true);
0846:
0847: String s;
0848:
0849: if (x == null) {
0850: s = "input stream is null";
0851:
0852: throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, s);
0853: }
0854:
0855: try {
0856: s = StringConverter.inputStreamToString(x, length);
0857:
0858: setParameter(parameterIndex, s);
0859: } catch (IOException e) {
0860: throw Util.sqlException(Trace.INVALID_CHARACTER_ENCODING);
0861: }
0862: }
0863:
0864: /**
0865: * <!-- start generic documentation -->
0866: * Sets the designated parameter to the given input stream, which
0867: * will have the specified number of bytes. A Unicode character has
0868: * two bytes, with the first byte being the high byte, and the second
0869: * being the low byte.
0870: *
0871: * When a very large Unicode value is input to a <code>LONGVARCHAR</code>
0872: * parameter, it may be more practical to send it via a
0873: * <code>java.io.InputStream</code> object. The data will be read from the
0874: * stream as needed until end-of-file is reached. The JDBC driver will
0875: * do any necessary conversion from Unicode to the database char format.
0876: *
0877: * <P><B>Note:</B> This stream object can either be a standard
0878: * Java stream object or your own subclass that implements the
0879: * standard interface.<p>
0880: * <!-- end generic documentation -->
0881: *
0882: * <!-- start release-specific documentation -->
0883: * <div class="ReleaseSpecificDocumentation">
0884: * <h3>HSQLDB-Specific Information:</h3> <p>
0885: *
0886: * Since 1.7.0, this method complies with behavior as defined by the
0887: * JDBC3 specification.
0888: * </div>
0889: * <!-- end release-specific documentation -->
0890: *
0891: * @param parameterIndex the first parameter is 1, the second is 2, ...
0892: * @param x a <code>java.io.InputStream</code> object that contains the
0893: * Unicode parameter value as two-byte Unicode characters
0894: * @param length the number of bytes in the stream
0895: * @exception SQLException if a database access error occurs
0896: * @deprecated Sun does not include a reason, but presumably
0897: * this is because setCharacterStream is now prefered
0898: */
0899:
0900: //#ifdef DEPRECATEDJDBC
0901: public void setUnicodeStream(int parameterIndex,
0902: java.io.InputStream x, int length) throws SQLException {
0903:
0904: checkSetParameterIndex(parameterIndex, true);
0905:
0906: String msg = null;
0907:
0908: if (x == null) {
0909: msg = "input stream is null";
0910: } else if (length % 2 != 0) {
0911: msg = "odd length argument";
0912: }
0913:
0914: if (msg != null) {
0915: throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
0916: }
0917:
0918: int chlen = length / 2;
0919: int chread = 0;
0920: StringBuffer sb = new StringBuffer();
0921: int hi;
0922: int lo;
0923:
0924: try {
0925: for (; chread < chlen; chread++) {
0926: hi = x.read();
0927:
0928: if (hi == -1) {
0929: break;
0930: }
0931:
0932: lo = x.read();
0933:
0934: if (lo == -1) {
0935: break;
0936: }
0937:
0938: sb.append((char) (hi << 8 | lo));
0939: }
0940: } catch (IOException e) {
0941: throw Util.sqlException(Trace.TRANSFER_CORRUPTED);
0942: }
0943:
0944: setParameter(parameterIndex, sb.toString());
0945: }
0946:
0947: //#endif
0948:
0949: /**
0950: * <!-- start generic documentation -->
0951: * Sets the designated parameter to the given input stream, which will have
0952: * the specified number of bytes.
0953: * When a very large binary value is input to a <code>LONGVARBINARY</code>
0954: * parameter, it may be more practical to send it via a
0955: * <code>java.io.InputStream</code> object. The data will be read from the
0956: * stream as needed until end-of-file is reached.
0957: *
0958: * <P><B>Note:</B> This stream object can either be a standard
0959: * Java stream object or your own subclass that implements the
0960: * standard interface.<p>
0961: * <!-- end generic documentation -->
0962: *
0963: * <!-- start release-specific documentation -->
0964: * <div class="ReleaseSpecificDocumentation">
0965: * <h3>HSQLDB-Specific Information:</h3> <p>
0966: *
0967: * Since 1.7.2, this method works according to the standard.
0968: * </div>
0969: * <!-- end release-specific documentation -->
0970: *
0971: * @param parameterIndex the first parameter is 1, the second is 2, ...
0972: * @param x the java input stream which contains the binary parameter value
0973: * @param length the number of bytes in the stream
0974: * @exception SQLException if a database access error occurs
0975: */
0976: public void setBinaryStream(int parameterIndex,
0977: java.io.InputStream x, int length) throws SQLException {
0978:
0979: checkSetParameterIndex(parameterIndex, true);
0980:
0981: if (x == null) {
0982: throw Util.sqlException(Trace
0983: .error(Trace.INVALID_JDBC_ARGUMENT,
0984: Trace.JDBC_NULL_STREAM));
0985: }
0986:
0987: HsqlByteArrayOutputStream out = null;
0988:
0989: try {
0990: out = new HsqlByteArrayOutputStream();
0991:
0992: int size = 2048;
0993: byte[] buff = new byte[size];
0994:
0995: for (int left = length; left > 0;) {
0996: int read = x.read(buff, 0, left > size ? size : left);
0997:
0998: if (read == -1) {
0999: break;
1000: }
1001:
1002: out.write(buff, 0, read);
1003:
1004: left -= read;
1005: }
1006:
1007: setParameter(parameterIndex, out.toByteArray());
1008: } catch (IOException e) {
1009: throw Util.sqlException(Trace.INPUTSTREAM_ERROR, e
1010: .toString());
1011: } finally {
1012: if (out != null) {
1013: try {
1014: out.close();
1015: } catch (IOException e) {
1016: }
1017: }
1018: }
1019: }
1020:
1021: /**
1022: * <!-- start generic documentation -->
1023: * Clears the current parameter values immediately. <p>
1024: *
1025: * In general, parameter values remain in force for repeated use of a
1026: * statement. Setting a parameter value automatically clears its
1027: * previous value. However, in some cases it is useful to immediately
1028: * release the resources used by the current parameter values; this can
1029: * be done by calling the method <code>clearParameters</code>.<p>
1030: * <!-- end generic documentation -->
1031: *
1032: * @exception SQLException if a database access error occurs
1033: */
1034: public void clearParameters() throws SQLException {
1035:
1036: checkClosed();
1037: ArrayUtil.fillArray(parameterValues, null);
1038: ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN,
1039: parameterSet, 0, parameterSet.length);
1040:
1041: if (parameterStream != null) {
1042: ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN,
1043: parameterStream, 0, parameterStream.length);
1044: }
1045: }
1046:
1047: //----------------------------------------------------------------------
1048: // Advanced features:
1049:
1050: /**
1051: * <!-- start generic documentation -->
1052: * Sets the value of the designated parameter with the given object. <p>
1053: *
1054: * The second argument must be an object type; for integral values, the
1055: * <code>java.lang</code> equivalent objects should be used. <p>
1056: *
1057: * The given Java object will be converted to the given targetSqlType
1058: * before being sent to the database.
1059: *
1060: * If the object has a custom mapping (is of a class implementing the
1061: * interface <code>SQLData</code>),
1062: * the JDBC driver should call the method <code>SQLData.writeSQL</code> to
1063: * write it to the SQL data stream.
1064: * If, on the other hand, the object is of a class implementing
1065: * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
1066: * <code>Struct</code>, or <code>Array</code>, the driver should pass it
1067: * to the database as a value of the corresponding SQL type. <p>
1068: *
1069: * Note that this method may be used to pass database-specific
1070: * abstract data types.<p>
1071: * <!-- end generic documentation -->
1072: *
1073: * <!-- start release-specific documentation -->
1074: * <div class="ReleaseSpecificDocumentation">
1075: * <h3>HSQLDB-Specific Information:</h3> <p>
1076: *
1077: * Inculding 1.7.1,this method was identical to
1078: * {@link #setObject(int, Object, int) setObject(int, Object, int)}.
1079: * That is, this method simply called setObject(int, Object, int),
1080: * ignoring the scale specification. <p>
1081: *
1082: * Since 1.7.2, this method supports the conversions listed in the
1083: * conversion table B-5 of the JDBC 3 specification. The scale argument
1084: * is not used.
1085: * </div>
1086: * <!-- start release-specific documentation -->
1087: *
1088: * @param parameterIndex the first parameter is 1, the second is 2, ...
1089: * @param x the object containing the input parameter value
1090: * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
1091: * sent to the database. The scale argument may further qualify this type.
1092: * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
1093: * this is the number of digits after the decimal point. For all
1094: * other types, this value will be ignored. <p>
1095: *
1096: * Up to and including HSQLDB 1.7.0, this parameter is ignored.
1097: * @exception SQLException if a database access error occurs
1098: * @see java.sql.Types
1099: * @see #setObject(int,Object,int)
1100: */
1101: public void setObject(int parameterIndex, Object x,
1102: int targetSqlType, int scale) throws SQLException {
1103:
1104: /** @todo fredt - implement SQLData support */
1105: setObject(parameterIndex, x);
1106: }
1107:
1108: /**
1109: * <!-- start generic documentation -->
1110: * Sets the value of the designated parameter with the given object.
1111: * This method is like the method <code>setObject</code>
1112: * above, except that it assumes a scale of zero. <p>
1113: * <!-- end generic documentation -->
1114: *
1115: * <!-- start release-specific documentation -->
1116: * <div class="ReleaseSpecificDocumentation">
1117: * <h3>HSQLDB-Specific Information:</h3> <p>
1118: *
1119: * Since 1.7.2, this method supports conversions listed in the
1120: * conversion table B-5 of the JDBC 3 specification.
1121: * </div>
1122: * <!-- end release-specific documentation -->
1123: *
1124: * @param parameterIndex the first parameter is 1, the second is 2, ...
1125: * @param x the object containing the input parameter value
1126: * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
1127: * sent to the database
1128: * @exception SQLException if a database access error occurs
1129: * @see #setObject(int,Object)
1130: */
1131: public void setObject(int parameterIndex, Object x,
1132: int targetSqlType) throws SQLException {
1133: setObject(parameterIndex, x);
1134: }
1135:
1136: /**
1137: * <!-- start generic documentation -->
1138: * Sets the value of the designated parameter using the given object. <p>
1139: *
1140: * The second parameter must be of type <code>Object</code>; therefore,
1141: * the <code>java.lang</code> equivalent objects should be used for
1142: * built-in types. <p>
1143: *
1144: * The JDBC specification specifies a standard mapping from
1145: * Java <code>Object</code> types to SQL types. The given argument
1146: * will be converted to the corresponding SQL type before being
1147: * sent to the database. <p>
1148: *
1149: * Note that this method may be used to pass datatabase-
1150: * specific abstract data types, by using a driver-specific Java
1151: * type. If the object is of a class implementing the interface
1152: * <code>SQLData</code>, the JDBC driver should call the method
1153: * <code>SQLData.writeSQL</code> to write it to the SQL data stream.
1154: * If, on the other hand, the object is of a class implementing
1155: * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
1156: * <code>Struct</code>, or <code>Array</code>, the driver should pass
1157: * it to the database as a value of the corresponding SQL type. <p>
1158: *
1159: * This method throws an exception if there is an ambiguity, for
1160: * example, if the object is of a class implementing more than one
1161: * of the interfaces named above.<p>
1162: * <!-- end generic documentation -->
1163: *
1164: * <!-- start release-specific documentation -->
1165: * <div class="ReleaseSpecificDocumentation">
1166: * <h3>HSQLDB-Specific Information:</h3><p>
1167: *
1168: * Since 1.7.2, this method supports conversions listed in the conversion
1169: * table B-5 of the JDBC 3 specification.<p>
1170: *
1171: * </div>
1172: *
1173: * @param parameterIndex the first parameter is 1, the second is 2, ...
1174: * @param x the object containing the input parameter value
1175: * @exception SQLException if a database access error occurs or the type
1176: * of the given object is ambiguous
1177: */
1178: public void setObject(int parameterIndex, Object x)
1179: throws SQLException {
1180: setParameter(parameterIndex, x);
1181: }
1182:
1183: //--------------------------JDBC 2.0-----------------------------
1184:
1185: /**
1186: * <!-- start generic documentation -->
1187: * Adds a set of parameters to this <code>PreparedStatement</code>
1188: * object's batch of commands. <p>
1189: * <!-- end generic documentation -->
1190: *
1191: * <!-- start release-specific documentation -->
1192: * <div class="ReleaseSpecificDocumentation">
1193: * <h3>HSQLDB-Specific Information:</h3> <p>
1194: *
1195: * Since 1.7.2, this feature is supported.
1196: * </div>
1197: * <!-- end release-specific documentation -->
1198: *
1199: * @exception SQLException if a database access error occurs
1200: * @see jdbcStatement#addBatch
1201: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1202: * jdbcPreparedStatement)
1203: */
1204: // boucherb@users 20030801 - method implemented
1205: public void addBatch() throws SQLException {
1206:
1207: checkClosed();
1208:
1209: int len = parameterValues.length;
1210: Object[] bpValues = new Object[len];
1211:
1212: checkParametersSet();
1213: System.arraycopy(parameterValues, 0, bpValues, 0, len);
1214:
1215: if (batchResultOut == null) {
1216: batchResultOut = new Result(ResultConstants.BATCHEXECUTE,
1217: parameterTypes, statementID);
1218: }
1219:
1220: batchResultOut.add(bpValues);
1221: }
1222:
1223: /**
1224: * <!-- start generic documentation -->
1225: * Sets the designated parameter to the given <code>Reader</code>
1226: * object, which is the given number of characters long.
1227: * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
1228: * parameter, it may be more practical to send it via a
1229: * <code>java.io.Reader</code> object. The data will be read from the
1230: * stream as needed until end-of-file is reached. The JDBC driver will
1231: * do any necessary conversion from UNICODE to the database char format.
1232: *
1233: * <P><B>Note:</B> This stream object can either be a standard
1234: * Java stream object or your own subclass that implements the
1235: * standard interface. <p>
1236: * <!-- end generic documentation -->
1237: *
1238: * <!-- start release-specific documentation -->
1239: * <div class="ReleaseSpecificDocumentation">
1240: * <h3>HSQLDB-Specific Information:</h3> <p>
1241: *
1242: * HSQLDB stores CHARACTER and related SQL types as Unicode so
1243: * this method does not perform any conversion.
1244: * </div>
1245: * <!-- end release-specific documentation -->
1246: *
1247: * @param parameterIndex the first parameter is 1, the second is 2, ...
1248: * @param reader the <code>java.io.Reader</code> object that contains the
1249: * Unicode data
1250: * @param length the number of characters in the stream
1251: * @exception SQLException if a database access error occurs
1252: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1253: * jdbcPreparedStatement)
1254: */
1255:
1256: // fredt@users 20020429 - patch 1.7.0 - method defined
1257: // fredt@users 20020627 - patch 574234 by ohioedge@users
1258: // boucherb@users 20030801 - patch 1.7.2 - updated
1259: public void setCharacterStream(int parameterIndex,
1260: java.io.Reader reader, int length) throws SQLException {
1261:
1262: checkSetParameterIndex(parameterIndex, true);
1263:
1264: if (reader == null) {
1265: String msg = "reader is null";
1266:
1267: throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1268: }
1269:
1270: final StringBuffer sb = new StringBuffer();
1271: final int size = 2048;
1272: final char[] buff = new char[size];
1273:
1274: try {
1275: for (int left = length; left > 0;) {
1276: final int read = reader.read(buff, 0,
1277: left > size ? size : left);
1278:
1279: if (read == -1) {
1280: break;
1281: }
1282:
1283: sb.append(buff, 0, read);
1284:
1285: left -= read;
1286: }
1287: } catch (IOException e) {
1288: throw Util.sqlException(Trace.TRANSFER_CORRUPTED, e
1289: .toString());
1290: }
1291:
1292: setParameter(parameterIndex, sb.toString());
1293: }
1294:
1295: /**
1296: * <!-- start generic documentation -->
1297: * Sets the designated parameter to the given
1298: * <code>REF(<structured-type>)</code> value.
1299: * The driver converts this to an SQL <code>REF</code> value when it
1300: * sends it to the database. <p>
1301: * <!-- end generic documentation -->
1302: *
1303: * <!-- start release-specific documentation -->
1304: * <div class="ReleaseSpecificDocumentation">
1305: * <h3>HSQLDB-Specific Information:</h3> <p>
1306: *
1307: * HSQLDB 1.7.2 does not support the SQL REF type. Calling this method
1308: * throws an exception.
1309: *
1310: * </div>
1311: * <!-- end release-specific documentation -->
1312: * @param i the first parameter is 1, the second is 2, ...
1313: * @param x an SQL <code>REF</code> value
1314: * @exception SQLException if a database access error occurs
1315: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1316: * jdbcPreparedStatement)
1317: */
1318: public void setRef(int i, Ref x) throws SQLException {
1319: throw Util.notSupported();
1320: }
1321:
1322: /**
1323: * <!-- start generic documentation -->
1324: * Sets the designated parameter to the given <code>Blob</code> object.
1325: * The driver converts this to an SQL <code>BLOB</code> value when it
1326: * sends it to the database. <p>
1327: * <!-- end generic documentation -->
1328: *
1329: * <!-- start release-specific documentation -->
1330: * <div class="ReleaseSpecificDocumentation">
1331: * <h3>HSQLDB-Specific Information:</h3> <p>
1332: *
1333: * Previous to 1.7.2, this feature was not supported. <p>
1334: *
1335: * Since 1.7.2, setBlob is supported. With 1.7.2, setting Blob objects is
1336: * limited to those of length less than or equal to Integer.MAX_VALUE.
1337: * In 1.7.2, setBlob(i,x) is roughly equivalent (null and length handling
1338: * not shown) to:
1339: *
1340: * <pre class="JavaCodeExample">
1341: * <b>setBinaryStream</b>(i, x.<b>getBinaryStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1342: * </pre></div>
1343: * <!-- end release-specific documentation -->
1344: *
1345: * @param i the first parameter is 1, the second is 2, ...
1346: * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code>
1347: * value
1348: * @exception SQLException if a database access error occurs
1349: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1350: * jdbcPreparedStatement)
1351: */
1352:
1353: // boucherb@users 20030801 - method implemented
1354: //#ifdef JAVA2
1355: public void setBlob(int i, Blob x) throws SQLException {
1356:
1357: if (x instanceof jdbcBlob) {
1358: setParameter(i, ((jdbcBlob) x).data);
1359:
1360: return;
1361: } else if (x == null) {
1362: setParameter(i, null);
1363:
1364: return;
1365: }
1366:
1367: checkSetParameterIndex(i, false);
1368:
1369: final long length = x.length();
1370:
1371: if (length > Integer.MAX_VALUE) {
1372: String msg = "Maximum Blob input octet length exceeded: "
1373: + length;
1374:
1375: throw Util.sqlException(Trace.INPUTSTREAM_ERROR, msg);
1376: }
1377:
1378: HsqlByteArrayOutputStream out = null;
1379:
1380: try {
1381: out = new HsqlByteArrayOutputStream();
1382:
1383: java.io.InputStream in = x.getBinaryStream();
1384: int buffSize = 2048;
1385: byte[] buff = new byte[buffSize];
1386:
1387: for (int left = (int) length; left > 0;) {
1388: int read = in.read(buff, 0, left > buffSize ? buffSize
1389: : left);
1390:
1391: if (read == -1) {
1392: break;
1393: }
1394:
1395: out.write(buff, 0, read);
1396:
1397: left -= read;
1398: }
1399:
1400: setParameter(i, out.toByteArray());
1401: } catch (IOException e) {
1402: throw Util.sqlException(Trace.INPUTSTREAM_ERROR, e
1403: .toString());
1404: } finally {
1405: if (out != null) {
1406: try {
1407: out.close();
1408: } catch (IOException e) {
1409: }
1410: }
1411: }
1412: }
1413:
1414: //#endif JAVA2
1415:
1416: /**
1417: * <!-- start generic documentation -->
1418: * Sets the designated parameter to the given <code>Clob</code> object.
1419: * The driver converts this to an SQL <code>CLOB</code> value when it
1420: * sends it to the database. <p>
1421: * <!-- end generic documentation -->
1422: *
1423: * <!-- start release-specific documentation -->
1424: * <div class="ReleaseSpecificDocumentation">
1425: * <h3>HSQLDB-Specific Information:</h3> <p>
1426: *
1427: * Previous to 1.7.2, this feature was not supported. <p>
1428: *
1429: * Since 1.7.2, setClob is supported. With 1.7.2, setting Blob objects is
1430: * limited to those of length less than or equal to Integer.MAX_VALUE.
1431: * In 1.7.2, setClob(i,x) is rougly equivalent (null and length handling
1432: * not shown) to: <p>
1433: *
1434: * <pre class="JavaCodeExample">
1435: * <b>setCharacterStream</b>(i, x.<b>getCharacterStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1436: * </pre></div>
1437: * <!-- end release-specific documentation -->
1438: * @param i the first parameter is 1, the second is 2, ...
1439: * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code>
1440: * value
1441: * @exception SQLException if a database access error occurs
1442: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1443: * jdbcPreparedStatement)
1444: */
1445: // boucherb@users 20030801 - method implemented
1446: //#ifdef JAVA2
1447: public void setClob(int i, Clob x) throws SQLException {
1448:
1449: if (x instanceof jdbcClob) {
1450: setParameter(i, ((jdbcClob) x).data);
1451:
1452: return;
1453: } else if (x == null) {
1454: setParameter(i, null);
1455:
1456: return;
1457: }
1458:
1459: checkSetParameterIndex(i, false);
1460:
1461: final long length = x.length();
1462:
1463: if (length > Integer.MAX_VALUE) {
1464: String msg = "Max Clob input character length exceeded: "
1465: + length;
1466:
1467: throw Util.sqlException(Trace.INPUTSTREAM_ERROR, msg);
1468: }
1469:
1470: java.io.Reader reader = x.getCharacterStream();
1471: final StringBuffer sb = new StringBuffer();
1472: final int size = 2048;
1473: final char[] buff = new char[size];
1474:
1475: try {
1476: for (int left = (int) length; left > 0;) {
1477: final int read = reader.read(buff, 0,
1478: left > size ? size : left);
1479:
1480: if (read == -1) {
1481: break;
1482: }
1483:
1484: sb.append(buff, 0, read);
1485:
1486: left -= read;
1487: }
1488: } catch (IOException e) {
1489: throw Util.sqlException(Trace.TRANSFER_CORRUPTED, e
1490: .toString());
1491: }
1492:
1493: setParameter(i, sb.toString());
1494: }
1495:
1496: //#endif JAVA2
1497:
1498: /**
1499: * <!-- start generic documentation -->
1500: * Sets the designated parameter to the given <code>Array</code> object.
1501: * The driver converts this to an SQL <code>ARRAY</code> value when it
1502: * sends it to the database. <p>
1503: * <!-- end generic documentation -->
1504: *
1505: * <!-- start release-specific documentation -->
1506: * <div class="ReleaseSpecificDocumentation">
1507: * <h3>HSQLDB-Specific Information:</h3> <p>
1508: *
1509: * HSQLDB 1.7.2 does not support the SQL ARRAY type. Calling this method
1510: * throws an exception.
1511: *
1512: * </div>
1513: * <!-- end release-specific documentation -->
1514: * @param i the first parameter is 1, the second is 2, ...
1515: * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code>
1516: * value
1517: * @exception SQLException if a database access error occurs
1518: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1519: * jdbcPreparedStatement)
1520: */
1521: public void setArray(int i, Array x) throws SQLException {
1522: throw Util.notSupported();
1523: }
1524:
1525: /**
1526: * <!-- start generic documentation -->
1527: * Retrieves a <code>ResultSetMetaData</code> object that contains
1528: * information about the columns of the <code>ResultSet</code> object
1529: * that will be returned when this <code>PreparedStatement</code> object
1530: * is executed.
1531: * <P>
1532: * Because a <code>PreparedStatement</code> object is precompiled, it is
1533: * possible to know about the <code>ResultSet</code> object that it will
1534: * return without having to execute it. Consequently, it is possible
1535: * to invoke the method <code>getMetaData</code> on a
1536: * <code>PreparedStatement</code> object rather than waiting to execute
1537: * it and then invoking the <code>ResultSet.getMetaData</code> method
1538: * on the <code>ResultSet</code> object that is returned.
1539: * <P>
1540: * <B>NOTE:</B> Using this method may be expensive for some drivers due
1541: * to the lack of underlying DBMS support. <p>
1542: * <!-- end generic documentation -->
1543: *
1544: * <!-- start release-specific documentation -->
1545: * <div class="ReleaseSpecificDocumentation">
1546: * <h3>HSQLDB-Specific Information:</h3> <p>
1547: *
1548: * Since 1.7.2, this feature is supported. If the statement
1549: * generates an update count, then null is returned.
1550: *
1551: * </div>
1552: * <!-- end release-specific documentation -->
1553: * @return the description of a <code>ResultSet</code> object's columns or
1554: * <code>null</code> if the driver cannot return a
1555: * <code>ResultSetMetaData</code> object
1556: * @exception SQLException if a database access error occurs
1557: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1558: * jdbcPreparedStatement)
1559: */
1560:
1561: // boucherb@users 20030801 - method implemented
1562: public ResultSetMetaData getMetaData() throws SQLException {
1563:
1564: checkClosed();
1565:
1566: if (isRowCount) {
1567: return null;
1568: }
1569:
1570: if (rsmd == null) {
1571: rsmd = new jdbcResultSetMetaData(rsmdDescriptor,
1572: connection.connProperties);
1573: }
1574:
1575: return rsmd;
1576: }
1577:
1578: /**
1579: * <!-- start generic documentation -->
1580: * Sets the designated parameter to the given <code>java.sql.Date</code>
1581: * value, using the given <code>Calendar</code> object. The driver uses
1582: * the <code>Calendar</code> object to construct an SQL <code>DATE</code>
1583: * value,which the driver then sends to the database. With a
1584: * a <code>Calendar</code> object, the driver can calculate the date
1585: * taking into account a custom timezone. If no
1586: * <code>Calendar</code> object is specified, the driver uses the default
1587: * timezone, which is that of the virtual machine running the
1588: * application. <p>
1589: * <!-- end generic documentation -->
1590: *
1591: * @param parameterIndex the first parameter is 1, the second is 2, ...
1592: * @param x the parameter value
1593: * @param cal the <code>Calendar</code> object the driver will use
1594: * to construct the date
1595: * @exception SQLException if a database access error occurs
1596: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1597: * jdbcPreparedStatement)
1598: */
1599:
1600: // fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1601: // changes by fredt - moved conversion to HsqlDateTime
1602: public void setDate(int parameterIndex, Date x, Calendar cal)
1603: throws SQLException {
1604:
1605: String s;
1606:
1607: try {
1608: s = HsqlDateTime.getDateString(x, cal);
1609: } catch (Exception e) {
1610: throw Util.sqlException(Trace.INVALID_ESCAPE, e.toString());
1611: }
1612:
1613: setParameter(parameterIndex, s);
1614: }
1615:
1616: /**
1617: * <!-- start generic documentation -->
1618: * Sets the designated parameter to the given <code>java.sql.Time</code>
1619: * value, using the given <code>Calendar</code> object. The driver uses
1620: * the <code>Calendar</code> object to construct an SQL <code>TIME</code>
1621: * value, which the driver then sends to the database. With a
1622: * a <code>Calendar</code> object, the driver can calculate the time
1623: * taking into account a custom timezone. If no
1624: * <code>Calendar</code> object is specified, the driver uses the default
1625: * timezone, which is that of the virtual machine running the
1626: * application. <p>
1627: * <!-- end generic documentation -->
1628: *
1629: * @param parameterIndex the first parameter is 1, the second is 2, ...
1630: * @param x the parameter value
1631: * @param cal the <code>Calendar</code> object the driver will use
1632: * to construct the time
1633: * @exception SQLException if a database access error occurs
1634: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1635: * jdbcPreparedStatement)
1636: */
1637:
1638: // fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1639: // changes by fredt - moved conversion to HsqlDateTime
1640: public void setTime(int parameterIndex, Time x, Calendar cal)
1641: throws SQLException {
1642:
1643: String s;
1644:
1645: try {
1646: s = HsqlDateTime.getTimeString(x, cal);
1647: } catch (Exception e) {
1648: throw Util.sqlException(Trace.INVALID_ESCAPE, e.toString());
1649: }
1650:
1651: setParameter(parameterIndex, s);
1652: }
1653:
1654: /**
1655: * <!-- start generic documentation -->
1656: * Sets the designated parameter to the given <code>java.sql.Timestamp</code>
1657: * value, using the given <code>Calendar</code> object. The driver uses
1658: * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code>
1659: * value, which the driver then sends to the database. With a
1660: * <code>Calendar</code> object, the driver can calculate the timestamp
1661: * taking into account a custom timezone. If no
1662: * <code>Calendar</code> object is specified, the driver uses the default
1663: * timezone, which is that of the virtual machine running the application. <p>
1664: * <!-- end generic documentation -->
1665: *
1666: * @param parameterIndex the first parameter is 1, the second is 2, ...
1667: * @param x the parameter value
1668: * @param cal the <code>Calendar</code> object the driver will use
1669: * to construct the timestamp
1670: * @exception SQLException if a database access error occurs
1671: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1672: * jdbcPreparedStatement)
1673: */
1674:
1675: // fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1676: // changes by fredt - moved conversion to HsqlDateTime
1677: public void setTimestamp(int parameterIndex, Timestamp x,
1678: Calendar cal) throws SQLException {
1679:
1680: checkSetParameterIndex(parameterIndex, false);
1681:
1682: if (cal != null && x != null) {
1683: int ns = x.getNanos();
1684:
1685: x = new Timestamp(HsqlDateTime
1686: .getTimeInMillis(x, cal, null));
1687:
1688: x.setNanos(ns);
1689: }
1690:
1691: setParameter(parameterIndex, x);
1692: }
1693:
1694: /**
1695: * <!-- start generic documentation -->
1696: * Sets the designated parameter to SQL <code>NULL</code>.
1697: * This version of the method <code>setNull</code> should
1698: * be used for user-defined types and REF type parameters. Examples
1699: * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
1700: * named array types.
1701: *
1702: * <P><B>Note:</B> To be portable, applications must give the
1703: * SQL type code and the fully-qualified SQL type name when specifying
1704: * a NULL user-defined or REF parameter. In the case of a user-defined
1705: * type the name is the type name of the parameter itself. For a REF
1706: * parameter, the name is the type name of the referenced type. If
1707: * a JDBC driver does not need the type code or type name information,
1708: * it may ignore it.
1709: *
1710: * Although it is intended for user-defined and Ref parameters,
1711: * this method may be used to set a null parameter of any JDBC type.
1712: * If the parameter does not have a user-defined or REF type, the given
1713: * typeName is ignored. <p>
1714: * <!-- end generic documentation -->
1715: *
1716: * <!-- start release-specific documentation -->
1717: * <div class="ReleaseSpecificDocumentation">
1718: * <h3>HSQLDB-Specific Information:</h3> <p>
1719: *
1720: * HSQLDB ignores the sqlType and typeName arguments.
1721: * </div>
1722: * <!-- end release-specific documentation -->
1723: *
1724: * @param paramIndex the first parameter is 1, the second is 2, ...
1725: * @param sqlType a value from <code>java.sql.Types</code>
1726: * @param typeName the fully-qualified name of an SQL user-defined type;
1727: * ignored if the parameter is not a user-defined type or REF
1728: * @exception SQLException if a database access error occurs
1729: * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1730: * jdbcPreparedStatement)
1731: */
1732: public void setNull(int paramIndex, int sqlType, String typeName)
1733: throws SQLException {
1734: setParameter(paramIndex, null);
1735: }
1736:
1737: //------------------------- JDBC 3.0 -----------------------------------
1738:
1739: /**
1740: * <!-- start generic documentation -->
1741: * Sets the designated parameter to the given <code>java.net.URL</code>
1742: * value. The driver converts this to an SQL <code>DATALINK</code> value
1743: * when it sends it to the database. <p>
1744: * <!-- end generic documentation -->
1745: *
1746: * <!-- start release-specific documentation -->
1747: * <div class="ReleaseSpecificDocumentation">
1748: * <h3>HSQLDB-Specific Information:</h3> <p>
1749: *
1750: * HSQLDB 1.7.2 does not support the DATALINK SQL type for which this
1751: * method is intended. Calling this method throws an exception.
1752: *
1753: * </div>
1754: * <!-- end release-specific documentation -->
1755: * @param parameterIndex the first parameter is 1, the second is 2, ...
1756: * @param x the <code>java.net.URL</code> object to be set
1757: * @exception SQLException if a database access error occurs
1758: * @since JDK 1.4, HSQL 1.7.0
1759: */
1760: //#ifdef JDBC3
1761: public void setURL(int parameterIndex, java.net.URL x)
1762: throws SQLException {
1763: throw Util.notSupported();
1764: }
1765:
1766: //#endif JDBC3
1767:
1768: /**
1769: * <!-- start generic documentation -->
1770: * Retrieves the number, types and properties of this
1771: * <code>PreparedStatement</code> object's parameters. <p>
1772: * <!-- end generic documentation -->
1773: *
1774: * <!-- start release-specific documentation -->
1775: * <div class="ReleaseSpecificDocumentation">
1776: * <h3>HSQLDB-Specific Information:</h3> <p>
1777: *
1778: * Since 1.7.2, this feature is supported.
1779: * </div>
1780: * <!-- end release-specific documentation -->
1781: *
1782: * @return a <code>ParameterMetaData</code> object that contains information
1783: * about the number, types and properties of this
1784: * <code>PreparedStatement</code> object's parameters
1785: * @exception SQLException if a database access error occurs
1786: * @see java.sql.ParameterMetaData
1787: * @since JDK 1.4, HSQL 1.7.0
1788: */
1789: // boucherb@users 20030801 - method implemented
1790: //#ifdef JDBC3
1791: public ParameterMetaData getParameterMetaData() throws SQLException {
1792:
1793: checkClosed();
1794:
1795: if (pmd == null) {
1796: pmd = new jdbcParameterMetaData(pmdDescriptor);
1797: }
1798:
1799: // NOTE: pmd is declared as Object to avoid yet another #ifdef.
1800: return (ParameterMetaData) pmd;
1801: }
1802:
1803: //#endif JDBC3
1804: //-------------------- Internal Implementation -----------------------------
1805:
1806: /**
1807: * Constructs a statement that produces results of the requested
1808: * <code>type</code>. <p>
1809: *
1810: * A prepared statement must be a single SQL statement. <p>
1811: *
1812: * @param c the Connection used execute this statement
1813: * @param sql the SQL statement this object represents
1814: * @param type the type of result this statement will produce
1815: * @throws HsqlException if the statement is not accepted by the database
1816: * @throws SQLException if preprocessing by driver fails
1817: */
1818: jdbcPreparedStatement(jdbcConnection c, String sql, int type)
1819: throws HsqlException, SQLException {
1820:
1821: super (c, type);
1822:
1823: sql = c.nativeSQL(sql);
1824:
1825: resultOut.setResultType(ResultConstants.SQLPREPARE);
1826: resultOut.setMainString(sql);
1827:
1828: Result in = connection.sessionProxy.execute(resultOut);
1829:
1830: if (in.isError()) {
1831: Util.throwError(in);
1832: }
1833:
1834: // else it's a MULTI result encapsulating three sub results:
1835: // 1.) a PREPARE_ACK
1836: //
1837: // Indicates the statement id to be communicated in SQLEXECUTE
1838: // requests to allow the engine to find the corresponding
1839: // CompiledStatement object, parameterize and execute it.
1840: //
1841: // 2.) a description of the statement's result set metadata
1842: //
1843: // This is communicated in the same way as for result sets. That is,
1844: // the metadata arrays of Result, such as colTypes, are used in the
1845: // "conventional" fashion. With some work, it may be possible
1846: // to speed up internal execution of prepared statements by
1847: // dispensing with generating most rsmd values while generating
1848: // the result, safe in the knowlege that the client already
1849: // has a copy of the rsmd. In general, only the colTypes array
1850: // must be available at the engine, and only for network
1851: // communications so that the row output and row input
1852: // interfaces can do their work. One caveat is that the
1853: // columnDisplaySize values are not accurate, as we do
1854: // not consistently enforce column size yet and instead
1855: // approximate the value when a result with actual data is
1856: // retrieved
1857: //
1858: // 3.) a description of the statement's parameter metadata
1859: //
1860: // This is communicated in a similar fashion to 2.), but has
1861: // a slighly different layout to allow the parameter modes
1862: // to be transmitted. The values of this object are used
1863: // to set up the parameter management of this class. The
1864: // object is also used to construct the jdbcParameterMetaData
1865: // object later, if requested. That is, it holds information
1866: // additional to that used by this class, so it should not be
1867: // altered or disposed of
1868: //
1869: // (boucherb@users)
1870: Iterator i;
1871:
1872: i = in.iterator();
1873:
1874: try {
1875: Object[] row;
1876:
1877: // PREPARE_ACK
1878: row = (Object[]) i.next();
1879: statementID = ((Result) row[0]).getStatementID();
1880:
1881: // DATA - isParameterDescription == false
1882: row = (Object[]) i.next();
1883: rsmdDescriptor = (Result) row[0];
1884: isRowCount = rsmdDescriptor.mode == ResultConstants.UPDATECOUNT;
1885:
1886: // DATA - isParameterDescription == true
1887: row = (Object[]) i.next();
1888: pmdDescriptor = (Result) row[0];
1889: parameterTypes = pmdDescriptor.metaData.getParameterTypes();
1890: parameterValues = new Object[parameterTypes.length];
1891: parameterSet = new boolean[parameterTypes.length];
1892: parameterModes = pmdDescriptor.metaData.paramMode;
1893: } catch (Exception e) {
1894: throw Trace.error(Trace.GENERAL_ERROR, e.toString());
1895: }
1896:
1897: resultOut = new Result(ResultConstants.SQLEXECUTE,
1898: parameterTypes, statementID);
1899:
1900: // for toString()
1901: this .sql = sql;
1902: }
1903:
1904: /**
1905: * Checks if execution does or does not generate a single row
1906: * update count, throwing if the argument, yes, does not match. <p>
1907: *
1908: * @param yes if true, check that execution generates a single
1909: * row update count, else check that execution generates
1910: * something other than a single row update count.
1911: * @throws SQLException if the argument, yes, does not match
1912: */
1913: protected void checkIsRowCount(boolean yes) throws SQLException {
1914:
1915: if (yes != isRowCount) {
1916: int msg = yes ? Trace.JDBC_STATEMENT_NOT_ROW_COUNT
1917: : Trace.JDBC_STATEMENT_NOT_RESULTSET;
1918:
1919: throw Util.sqlException(msg);
1920: }
1921: }
1922:
1923: /**
1924: * Checks if the specified parameter index value is valid in terms of
1925: * setting an IN or IN OUT parameter value. <p>
1926: *
1927: * @param i The parameter index to check
1928: * @throws SQLException if the specified parameter index is invalid
1929: */
1930: protected void checkSetParameterIndex(int i, boolean isStream)
1931: throws SQLException {
1932:
1933: int mode;
1934: String msg;
1935:
1936: checkClosed();
1937:
1938: if (i < 1 || i > parameterValues.length) {
1939: msg = "parameter index out of range: " + i;
1940:
1941: throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1942: }
1943:
1944: if (isStream) {
1945: if (parameterStream == null) {
1946: parameterStream = new boolean[parameterTypes.length];
1947: }
1948:
1949: parameterStream[i - 1] = true;
1950: parameterSet[i - 1] = false;
1951: } else {
1952: parameterSet[i - 1] = true;
1953: }
1954: /*
1955: mode = parameterModes[i - 1];
1956:
1957: switch (mode) {
1958:
1959: default :
1960: msg = "Not IN or IN OUT mode: " + mode + " for parameter: "
1961: + i;
1962:
1963: throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1964: case Expression.PARAM_IN :
1965: case Expression.PARAM_IN_OUT :
1966: break;
1967: }
1968: */
1969: }
1970:
1971: /**
1972: * Called just before execution or adding to batch, this ensures all the
1973: * parameters have been set.<p>
1974: *
1975: * If a parameter has been set using a stream method, it should be set
1976: * again for the next reuse. When set using other methods, the parameter
1977: * setting is retained for the next use.
1978: */
1979: private void checkParametersSet() throws SQLException {
1980: ;
1981: }
1982:
1983: /*
1984: // do not check for compatibility with 1.8.0.x
1985: private void checkParametersSet() throws SQLException {
1986:
1987: if (parameterStream == null) {
1988: for (int i = 0; i < parameterSet.length; i++) {
1989: if (!parameterSet[i]) {
1990: throw Util.sqlException(Trace.JDBC_PARAMETER_NOT_SET);
1991: }
1992: }
1993: } else {
1994: for (int i = 0; i < parameterSet.length; i++) {
1995: if (!parameterSet[i] &&!parameterStream[i]) {
1996: throw Util.sqlException(Trace.JDBC_PARAMETER_NOT_SET);
1997: }
1998: }
1999:
2000: ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN,
2001: parameterStream, 0, parameterStream.length);
2002: }
2003: }
2004: */
2005:
2006: /**
2007: * The internal parameter value setter always converts the parameter to
2008: * the Java type required for data transmission. Target BINARY and OTHER
2009: * types are converted directly. All other target types are converted
2010: * by Column.convertObject(). This also normalizes DATETIME values.
2011: *
2012: * @param i parameter index
2013: * @param o object
2014: * @throws SQLException if either argument is not acceptable.
2015: */
2016: private void setParameter(int i, Object o) throws SQLException {
2017:
2018: checkSetParameterIndex(i, false);
2019:
2020: i--;
2021:
2022: if (o == null) {
2023: parameterValues[i] = null;
2024:
2025: return;
2026: }
2027:
2028: int outType = parameterTypes[i];
2029:
2030: try {
2031: switch (outType) {
2032:
2033: case Types.OTHER:
2034: o = new JavaObject((Serializable) o);
2035: break;
2036:
2037: case Types.BINARY:
2038: case Types.VARBINARY:
2039: case Types.LONGVARBINARY:
2040: if (!(o instanceof byte[])) {
2041: throw Util.sqlException(Trace
2042: .error(Trace.INVALID_CONVERSION));
2043: }
2044:
2045: o = new Binary((byte[]) o, !connection.isNetConn);
2046: break;
2047:
2048: case Types.DATE:
2049: if (o instanceof java.util.Date) {
2050: long t = HsqlDateTime
2051: .getNormalisedDate(((java.util.Date) o)
2052: .getTime());
2053:
2054: o = new Date(t);
2055: } else {
2056: o = Column.convertObject(o, outType);
2057: }
2058: break;
2059:
2060: case Types.TIME:
2061: if (o instanceof java.util.Date) {
2062: long m = HsqlDateTime
2063: .getNormalisedTime(((java.util.Date) o)
2064: .getTime());
2065:
2066: o = new Time(m);
2067: } else {
2068: o = Column.convertObject(o, outType);
2069: }
2070: break;
2071:
2072: case Types.TIMESTAMP:
2073: if (o instanceof Timestamp) {
2074: long m = ((Timestamp) o).getTime();
2075: int n = ((Timestamp) o).getNanos();
2076:
2077: o = new Timestamp(m);
2078:
2079: ((Timestamp) o).setNanos(n);
2080: } else {
2081: o = Column.convertObject(o, outType);
2082: }
2083: break;
2084:
2085: default:
2086: o = Column.convertObject(o, outType);
2087: break;
2088: }
2089: } catch (HsqlException e) {
2090: Util.throwError(e);
2091: }
2092:
2093: parameterValues[i] = o;
2094: }
2095:
2096: /**
2097: * Used with int and narrower integral primitives
2098: * @param i parameter index
2099: * @param value object to set
2100: * @throws SQLException if either argument is not acceptable
2101: */
2102: private void setIntParameter(int i, int value) throws SQLException {
2103:
2104: checkSetParameterIndex(i, false);
2105:
2106: int outType = parameterTypes[i - 1];
2107:
2108: switch (outType) {
2109:
2110: case Types.TINYINT:
2111: case Types.SMALLINT:
2112: case Types.INTEGER:
2113: Object o = new Integer(value);
2114:
2115: parameterValues[i - 1] = o;
2116: break;
2117:
2118: default:
2119: setLongParameter(i, value);
2120: }
2121: }
2122:
2123: /**
2124: * Used with long and narrower integral primitives. Conversion to BINARY
2125: * or OTHER types will throw here and not passed to setParameter().
2126: *
2127: * @param i parameter index
2128: * @param value object to set
2129: * @throws SQLException if either argument is not acceptable
2130: */
2131: private void setLongParameter(int i, long value)
2132: throws SQLException {
2133:
2134: checkSetParameterIndex(i, false);
2135:
2136: int outType = parameterTypes[i - 1];
2137:
2138: switch (outType) {
2139:
2140: case Types.BIGINT:
2141: Object o = new Long(value);
2142:
2143: parameterValues[i - 1] = o;
2144: break;
2145:
2146: case Types.BINARY:
2147: case Types.OTHER:
2148: throw Util.sqlException(Trace
2149: .error(Trace.INVALID_CONVERSION));
2150: default:
2151: setParameter(i, new Long(value));
2152: }
2153: }
2154:
2155: /**
2156: * This method should always throw if called for a PreparedStatement or
2157: * CallableStatment.
2158: *
2159: * @param sql ignored
2160: * @throws SQLException always
2161: */
2162: public void addBatch(String sql) throws SQLException {
2163: throw Util.notSupported();
2164: }
2165:
2166: /**
2167: * This method should always throw if called for a PreparedStatement or
2168: * CallableStatment.
2169: *
2170: * @param sql ignored
2171: * @throws SQLException always
2172: * @return nothing
2173: */
2174: public ResultSet executeQuery(String sql) throws SQLException {
2175: throw Util.notSupported();
2176: }
2177:
2178: /**
2179: * This method should always throw if called for a PreparedStatement or
2180: * CallableStatment.
2181: *
2182: * @param sql ignored
2183: * @throws SQLException always
2184: * @return nothing
2185: */
2186: public boolean execute(String sql) throws SQLException {
2187: throw Util.notSupported();
2188: }
2189:
2190: /**
2191: * This method should always throw if called for a PreparedStatement or
2192: * CallableStatment.
2193: *
2194: * @param sql ignored
2195: * @throws SQLException always
2196: * @return nothing
2197: */
2198: public int executeUpdate(String sql) throws SQLException {
2199: throw Util.notSupported();
2200: }
2201:
2202: /**
2203: * Does the specialized work required to free this object's resources and
2204: * that of it's parent class. <p>
2205: *
2206: * @throws SQLException if a database access error occurs
2207: */
2208: public synchronized void close() throws SQLException {
2209:
2210: if (isClosed()) {
2211: return;
2212: }
2213:
2214: HsqlException he = null;
2215:
2216: try {
2217:
2218: // fredt - if this is called by Connection.close() then there's no
2219: // need to free the prepared statements on the server - it is done
2220: // by Connection.close()
2221: if (!connection.isClosed) {
2222: connection.sessionProxy.execute(Result
2223: .newFreeStmtRequest(statementID));
2224: }
2225: } catch (HsqlException e) {
2226: he = e;
2227: }
2228:
2229: parameterValues = null;
2230: parameterSet = null;
2231: parameterStream = null;
2232: parameterTypes = null;
2233: parameterModes = null;
2234: rsmdDescriptor = null;
2235: pmdDescriptor = null;
2236: rsmd = null;
2237: pmd = null;
2238:
2239: super .close();
2240:
2241: if (he != null) {
2242: throw Util.sqlException(he);
2243: }
2244: }
2245:
2246: /**
2247: * Retrieves a String representation of this object. <p>
2248: *
2249: * The representation is of the form: <p>
2250: *
2251: * class-name@hash[sql=[char-sequence], parameters=[p1, ...pi, ...pn]] <p>
2252: *
2253: * p1, ...pi, ...pn are the String representations of the currently set
2254: * parameter values that will be used with the non-batch execution
2255: * methods. <p>
2256: *
2257: * @return a String representation of this object
2258: */
2259: public String toString() {
2260:
2261: StringBuffer sb = new StringBuffer();
2262: String sql;
2263: Object[] pv;
2264:
2265: sb.append(super .toString());
2266:
2267: sql = this .sql;
2268: pv = parameterValues;
2269:
2270: if (sql == null || pv == null) {
2271: sb.append("[closed]");
2272:
2273: return sb.toString();
2274: }
2275:
2276: sb.append("[sql=[").append(sql).append("]");
2277:
2278: if (pv.length > 0) {
2279: sb.append(", parameters=[");
2280:
2281: for (int i = 0; i < pv.length; i++) {
2282: sb.append('[');
2283: sb.append(pv[i]);
2284: sb.append("], ");
2285: }
2286:
2287: sb.setLength(sb.length() - 2);
2288: sb.append(']');
2289: }
2290:
2291: sb.append(']');
2292:
2293: return sb.toString();
2294: }
2295: }
|