KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > jdbc > jdbcPreparedStatement


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb.jdbc;
33
34 import java.io.IOException JavaDoc;
35 import java.io.Serializable JavaDoc;
36 import java.math.BigDecimal JavaDoc;
37 import java.sql.Date JavaDoc;
38 import java.sql.PreparedStatement JavaDoc;
39 import java.sql.ResultSet JavaDoc;
40 import java.sql.ResultSetMetaData JavaDoc;
41 import java.sql.SQLException JavaDoc;
42 import java.sql.Time JavaDoc;
43 import java.sql.Timestamp JavaDoc;
44 import java.util.Calendar JavaDoc;
45
46 //#ifdef JAVA2
47
import java.sql.Array JavaDoc;
48 import java.sql.Blob JavaDoc;
49 import java.sql.Clob JavaDoc;
50 import java.sql.Ref JavaDoc;
51
52 //#endif JAVA2
53
//#ifdef JDBC3
54
import java.sql.ParameterMetaData JavaDoc;
55
56 //#endif JDBC3
57
import org.hsqldb.Column;
58 import org.hsqldb.HsqlDateTime;
59 import org.hsqldb.HsqlException;
60 import org.hsqldb.Result;
61 import org.hsqldb.ResultConstants;
62 import org.hsqldb.Trace;
63 import org.hsqldb.Types;
64 import org.hsqldb.lib.ArrayUtil;
65 import org.hsqldb.lib.HsqlByteArrayOutputStream;
66 import org.hsqldb.lib.Iterator;
67 import org.hsqldb.lib.StringConverter;
68 import org.hsqldb.types.Binary;
69 import org.hsqldb.types.JavaObject;
70
71 // fredt@users 20020320 - patch 1.7.0 - JDBC 2 support and error trapping
72
// JDBC 2 methods can now be called from jdk 1.1.x - see javadoc comments
73
// boucherb@users 20020509 - added "throws SQLException" to all methods where
74
// it was missing here but specified in the java.sql.PreparedStatement and
75
// java.sqlCallableStatement interfaces, updated generic documentation to
76
// JDK 1.4, and added JDBC3 methods and docs
77
// boucherb@users and fredt@users 20020409/20020505 extensive review and update
78
// of docs and behaviour to comply with previous and latest java.sql specification
79
// fredt@users 20030620 - patch 1.7.2 - rewritten to support real prepared statements
80
// boucherb@users 20030801 - patch 1.7.2 - support for batch execution
81
// boucherb@users 20030801 - patch 1.7.2 - support for getMetaData and getParameterMetadata
82
// boucherb@users 20030801 - patch 1.7.2 - updated some setXXX methods
83
// boucherb@users 200403/4xx - doc 1.7.2 - javadoc updates toward 1.7.2 final
84
// boucherb@users 200403/4xx - patch 1.7.2 - eliminate eager buffer allocation from setXXXStream/Blob/Clob
85
// fredt@users 20060215 - patch 1.8.0 - check for unset parameters
86

87 /**
88  * <!-- start generic documentation -->
89  *
90  * An object that represents a precompiled SQL statement. <p>
91  *
92  * An SQL statement is precompiled and stored in a
93  * <code>PreparedStatement</code> object. This object can then be used to
94  * efficiently execute this statement multiple times.
95  *
96  * <P><B>Note:</B> The setter methods (<code>setShort</code>,
97  * <code>setString</code>, and so on) for setting IN parameter values
98  * must specify types that are compatible with the defined SQL type of
99  * the input parameter. For instance, if the IN parameter has SQL type
100  * <code>INTEGER</code>, then the method <code>setInt</code> should be
101  * used. <p>
102  *
103  * If arbitrary parameter type conversions are required, the method
104  * <code>setObject</code> should be used with a target SQL type.
105  * <P>
106  * In the following example of setting a parameter, <code>con</code>
107  * represents an active connection:
108  * <PRE>
109  * PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
110  * SET SALARY = ? WHERE ID = ?");
111  * pstmt.setBigDecimal(1, 153833.00)
112  * pstmt.setInt(2, 110592)
113  * </PRE> <p>
114  * <!-- end generic documentation -->
115  * <!-- start Release-specific documentation -->
116  * <div class="ReleaseSpecificDocumentation">
117  * <h3>HSQLDB-Specific Information:</h3> <p>
118  *
119  * Starting with HSQLDB 1.7.2, jdbcPreparedStatement objects are backed by
120  * a true compiled parameteric representation. Hence, there are now significant
121  * performance gains to be had by using a jdbcPreparedStatement object in
122  * preference to a jdbcStatement object, if a short-running SQL statement is
123  * to be executed more than a small number of times. <p>
124  *
125  * When it can be otherwise avoided, it is to be considered poor
126  * practice to fully prepare (construct), parameterize, execute, fetch and
127  * close a jdbcPreparedStatement object for each execution cycle. Indeed, under
128  * HSQLDB 1.8.0, this practice is likely to be noticably <em>less</em>
129  * performant for short-running statements than the equivalent process using
130  * jdbcStatement objects, albeit far more convenient, less error prone and
131  * certainly much less resource-intensive, especially when large binary and
132  * character values are involved, due to the optimized parameterization
133  * facility. <p>
134  *
135  * Instead, when developing an application that is not totally oriented toward
136  * the execution of ad hoc SQL, it is recommended to expend some effort toward
137  * identifing the SQL statements that are good candidates for regular reuse and
138  * adapting the structure of the application accordingly. Often, this is done
139  * by recording the text of candidate SQL statements in an application resource
140  * object (which has the nice side-benefit of isolating and hiding differences
141  * in SQL dialects across different drivers) and caching for possible reuse the
142  * PreparedStatement objects derived from the recorded text. <p>
143  *
144  * <b>Multi thread use:</b> <p>
145  *
146  * A PreparedStatement object is stateful and should not normally be shared
147  * by multiple threads. If it has to be shared, the calls to set the
148  * parameters, calls to add batch statements, the execute call and any
149  * post-execute calls should be made within a block synchronized on the
150  * PreparedStatement Object.<p>
151  *
152  * <b>JRE 1.1.x Notes:</b> <p>
153  *
154  * In general, JDBC 2 support requires Java 1.2 and above, and JDBC3 requires
155  * Java 1.4 and above. In HSQLDB, support for methods introduced in different
156  * versions of JDBC depends on the JDK version used for compiling and building
157  * HSQLDB.<p>
158  *
159  * Since 1.7.0, it is possible to build the product so that
160  * all JDBC 2 methods can be called while executing under the version 1.1.x
161  * <em>Java Runtime Environment</em><sup><font size="-2">TM</font></sup>.
162  * However, in addition to requiring explicit casts to the org.hsqldb.jdbcXXX
163  * interface implementations, some of these method calls require
164  * <code>int</code> values that are defined only in the JDBC 2 or greater
165  * version of
166  * <a HREF="http://java.sun.com/j2se/1.4/docs/api/java/sql/ResultSet.html">
167  * <code>ResultSet</code></a> interface. For this reason, when the
168  * product is compiled under JDK 1.1.x, these values are defined in
169  * {@link jdbcResultSet jdbcResultSet}.<p>
170  *
171  * In a JRE 1.1.x environment, calling JDBC 2 methods that take or return the
172  * JDBC2-only <code>ResultSet</code> values can be achieved by referring
173  * to them in parameter specifications and return value comparisons,
174  * respectively, as follows: <p>
175  *
176  * <pre class="JavaCodeExample">
177  * jdbcResultSet.FETCH_FORWARD
178  * jdbcResultSet.TYPE_FORWARD_ONLY
179  * jdbcResultSet.TYPE_SCROLL_INSENSITIVE
180  * jdbcResultSet.CONCUR_READ_ONLY
181  * // etc.
182  * </pre>
183  *
184  * However, please note that code written in such a manner will not be
185  * compatible for use with other JDBC 2 drivers, since they expect and use
186  * <code>ResultSet</code>, rather than <code>jdbcResultSet</code>. Also
187  * note, this feature is offered solely as a convenience to developers
188  * who must work under JDK 1.1.x due to operating constraints, yet wish to
189  * use some of the more advanced features available under the JDBC 2
190  * specification.<p>
191  *
192  * (fredt@users)<br>
193  * (boucherb@users)
194  * </div>
195  * <!-- end Release-specific documentation -->
196  *
197  * @author boucherb@users
198  * @author fredt@users
199  * @version 1.8.0
200  * @see jdbcConnection#prepareStatement
201  * @see jdbcResultSet
202  */

203 public class jdbcPreparedStatement extends jdbcStatement
204 implements PreparedStatement JavaDoc {
205
206     /** The parameter values for the next non-batch execution. */
207     protected Object JavaDoc[] parameterValues;
208
209     /** Flags for bound variables. */
210     protected boolean[] parameterSet;
211
212     /** Flags for bound stream variables. */
213     protected boolean[] parameterStream;
214
215     /** The SQL types of the parameters. */
216     protected int[] parameterTypes;
217
218     /** The (IN, IN OUT, or OUT) modes of parameters */
219     protected int[] parameterModes;
220
221     /** Lengths for streams. */
222     protected int[] streamLengths;
223
224     /** Has a stream or CLOB / BLOB parameter value. */
225     protected boolean hasStreams;
226
227     /**
228      * Description of result set metadata. <p>
229      */

230     protected Result rsmdDescriptor;
231
232     /** Description of parameter metadata. */
233     protected Result pmdDescriptor;
234
235     /** This object's one and one ResultSetMetaData object. */
236     protected jdbcResultSetMetaData rsmd;
237
238 // NOTE: pmd is declared as Object to avoid yet another #ifdef.
239

240     /** This object's one and only ParameterMetaData object. */
241     protected Object JavaDoc pmd;
242
243     /** The SQL character sequence that this object represents. */
244     protected String JavaDoc sql;
245
246     /**
247      * The id with which this object's corresponding
248      * {@link org.hsqldb.CompiledStatement CompiledStatement}
249      * object is registered in the engine's
250      * {@link org.hsqldb.CompiledStatementManager CompiledStatementManager}
251      * object.
252      */

253     protected int statementID;
254
255     /**
256      * Whether this statement generates only a single row update count in
257      * response to execution.
258      */

259     protected boolean isRowCount;
260
261 // fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
262
// fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
263
//
264
// changes by fredt
265
// SimpleDateFormat objects moved out of methods to improve performance
266
// this is safe because only one thread at a time should access a
267
// PreparedStatement object until it has finished executing the statement
268
// fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
269
// minor changes by fredt
270

271     /**
272      * <!-- start generic documentation -->
273      * Sets escape processing on or off. <p>
274      * <!-- end generic documentation -->
275      *
276      * <!-- start release-specific documentation -->
277      * <div class="ReleaseSpecificDocumentation">
278      * <h3>HSQLDB-Specific Information:</h3> <p>
279      *
280      * Since 1.7.0, the implementation follows the standard
281      * behaviour by overriding the same method in jdbcStatement
282      * class. <p>
283      *
284      * In other words, calling this method has no effect.
285      * </div>
286      * <!-- end release-specific documentation -->
287      *
288      * @param enable <code>true</code> to enable escape processing;
289      * <code>false</code> to disable it
290      * @exception SQLException if a database access error occurs
291      */

292     public void setEscapeProcessing(boolean enable) throws SQLException JavaDoc {
293         checkClosed();
294     }
295
296     /**
297      * <!-- start generic documentation -->
298      * Executes the SQL statement in this <code>PreparedStatement</code>
299      * object, which may be any kind of SQL statement.
300      * Some prepared statements return multiple results; the
301      * <code>execute</code> method handles these complex statements as well
302      * as the simpler form of statements handled by the methods
303      * <code>executeQuery</code>and <code>executeUpdate</code>. <p>
304      *
305      * The <code>execute</code> method returns a <code>boolean</code> to
306      * indicate the form of the first result. You must call either the method
307      * <code>getResultSet</code> or <code>getUpdateCount</code>
308      * to retrieve the result; you must call <code>getMoreResults</code> to
309      * move to any subsequent result(s). <p>
310      * <!-- end generic documentation -->
311      *
312      * <!-- start release-specific documentation -->
313      * <div class="ReleaseSpecificDocumentation">
314      * <h3>HSQLDB-Specific Information:</h3> <p>
315      *
316      * Including 1.8.0, prepared statements do not generate
317      * multiple fetchable results. <p>
318      *
319      * In future versions, it will be possible that statements
320      * generate multiple fetchable results under certain conditions.
321      * </div>
322      *
323      * @return <code>true</code> if the first result is a <code>ResultSet</code>
324      * object; <code>false</code> if the first result is an update
325      * count or there is no result
326      * @exception SQLException if a database access error occurs or an argument
327      * is supplied to this method
328      * @see jdbcStatement#execute
329      * @see jdbcStatement#getResultSet
330      * @see jdbcStatement#getUpdateCount
331      * @see jdbcStatement#getMoreResults
332      */

333     public boolean execute() throws SQLException JavaDoc {
334
335         checkClosed();
336         connection.clearWarningsNoCheck();
337
338         resultIn = null;
339
340         try {
341             resultOut.setMaxRows(maxRows);
342             resultOut.setParameterData(parameterValues);
343
344             resultIn = connection.sessionProxy.execute(resultOut);
345         } catch (HsqlException e) {
346             throw Util.sqlException(e);
347         }
348
349         if (resultIn.isError()) {
350             Util.throwError(resultIn);
351         }
352
353         return resultIn.isData();
354     }
355
356     /**
357      * <!-- start generic documentation -->
358      * Executes the SQL query in this <code>PreparedStatement</code> object
359      * and returns the <code>ResultSet</code> object generated by the query.<p>
360      * <!-- end generic documentation -->
361      *
362      * @return a <code>ResultSet</code> object that contains the data produced
363      * by the query; never <code>null</code>
364      * @exception SQLException if a database access error occurs or the SQL
365      * statement does not return a <code>ResultSet</code> object
366      */

367     public ResultSet JavaDoc executeQuery() throws SQLException JavaDoc {
368
369         checkClosed();
370         connection.clearWarningsNoCheck();
371         checkIsRowCount(false);
372         checkParametersSet();
373
374         resultIn = null;
375
376         try {
377             resultOut.setMaxRows(maxRows);
378             resultOut.setParameterData(parameterValues);
379
380             resultIn = connection.sessionProxy.execute(resultOut);
381         } catch (HsqlException e) {
382             throw Util.sqlException(e);
383         }
384
385         if (resultIn.isError()) {
386             Util.throwError(resultIn);
387         } else if (!resultIn.isData()) {
388             String JavaDoc msg = "Expected but did not recieve a result set";
389
390             throw Util.sqlException(Trace.UNEXPECTED_EXCEPTION, msg);
391         }
392
393         return new jdbcResultSet(this, resultIn, connection.connProperties,
394                                  connection.isNetConn);
395     }
396
397     /**
398      * <!-- start generic documentation -->
399      * Executes the SQL statement in this <code>PreparedStatement</code>
400      * object, which must be an SQL <code>INSERT</code>,
401      * <code>UPDATE</code> or <code>DELETE</code> statement; or an SQL
402      * statement that returns nothing, such as a DDL statement.<p>
403      * <!-- end generic documentation -->
404      *
405      * @return either (1) the row count for <code>INSERT</code>,
406      * <code>UPDATE</code>, or <code>DELETE</code>
407      * statements or (2) 0 for SQL statements that
408      * return nothing
409      * @exception SQLException if a database access error occurs or the SQL
410      * statement returns a <code>ResultSet</code> object
411      */

412     public int executeUpdate() throws SQLException JavaDoc {
413
414         checkClosed();
415         connection.clearWarningsNoCheck();
416         checkIsRowCount(true);
417         checkParametersSet();
418
419         resultIn = null;
420
421         try {
422             resultOut.setParameterData(parameterValues);
423
424             resultIn = connection.sessionProxy.execute(resultOut);
425         } catch (HsqlException e) {
426             throw Util.sqlException(e);
427         }
428
429         if (resultIn.isError()) {
430             Util.throwError(resultIn);
431         } else if (resultIn.mode != ResultConstants.UPDATECOUNT) {
432             String JavaDoc msg = "Expected but did not recieve a row update count";
433
434             throw Util.sqlException(Trace.UNEXPECTED_EXCEPTION, msg);
435         }
436
437         return resultIn.getUpdateCount();
438     }
439
440     /**
441      * <!-- start generic documentation -->
442      * Submits a batch of commands to the database for execution and
443      * if all commands execute successfully, returns an array of update counts.
444      * The <code>int</code> elements of the array that is returned are ordered
445      * to correspond to the commands in the batch, which are ordered
446      * according to the order in which they were added to the batch.
447      * The elements in the array returned by the method <code>executeBatch</code>
448      * may be one of the following:
449      * <OL>
450      * <LI>A number greater than or equal to zero -- indicates that the
451      * command was processed successfully and is an update count giving the
452      * number of rows in the database that were affected by the command's
453      * execution
454      * <LI>A value of <code>SUCCESS_NO_INFO</code> -- indicates that the command was
455      * processed successfully but that the number of rows affected is
456      * unknown
457      * <P>
458      * If one of the commands in a batch update fails to execute properly,
459      * this method throws a <code>BatchUpdateException</code>, and a JDBC
460      * driver may or may not continue to process the remaining commands in
461      * the batch. However, the driver's behavior must be consistent with a
462      * particular DBMS, either always continuing to process commands or never
463      * continuing to process commands. If the driver continues processing
464      * after a failure, the array returned by the method
465      * <code>BatchUpdateException.getUpdateCounts</code>
466      * will contain as many elements as there are commands in the batch, and
467      * at least one of the elements will be the following:
468      * <P>
469      * <LI>A value of <code>EXECUTE_FAILED</code> -- indicates that the command failed
470      * to execute successfully and occurs only if a driver continues to
471      * process commands after a command fails
472      * </OL>
473      * <P>
474      * A driver is not required to implement this method.
475      * The possible implementations and return values have been modified in
476      * the Java 2 SDK, Standard Edition, version 1.3 to
477      * accommodate the option of continuing to proccess commands in a batch
478      * update after a <code>BatchUpdateException</code> obejct has been thrown. <p>
479      * <!-- end generic documentation -->
480      *
481      * <!-- start release-specific documentation -->
482      * <div class="ReleaseSpecificDocumentation">
483      * <h3>HSQLDB-Specific Information:</h3> <p>
484      *
485      * Starting with HSQLDB 1.7.2, this feature is supported. <p>
486      *
487      * HSQLDB stops execution of commands in a batch when one of the commands
488      * results in an exception. The size of the returned array equals the
489      * number of commands that were executed successfully.<p>
490      *
491      * When the product is built under the JAVA1 target, an exception
492      * is never thrown and it is the responsibility of the client software to
493      * check the size of the returned update count array to determine if any
494      * batch items failed. To build and run under the JAVA2 target, JDK/JRE
495      * 1.3 or higher must be used.
496      * </div>
497      * <!-- end release-specific documentation -->
498      *
499      * @return an array of update counts containing one element for each
500      * command in the batch. The elements of the array are ordered according
501      * to the order in which commands were added to the batch.
502      * @exception SQLException if a database access error occurs or the
503      * driver does not support batch statements. Throws
504      * {@link java.sql.BatchUpdateException}
505      * (a subclass of <code>java.sql.SQLException</code>) if one of the commands
506      * sent to the database fails to execute properly or attempts to return a
507      * result set.
508      * @since JDK 1.3 (JDK 1.1.x developers: read the new overview
509      * for jdbcStatement)
510      */

511     public int[] executeBatch() throws SQLException JavaDoc {
512
513         if (batchResultOut == null) {
514             batchResultOut = new Result(ResultConstants.BATCHEXECUTE,
515                                         parameterTypes, statementID);
516         }
517
518         return super.executeBatch();
519     }
520
521     /**
522      * <!-- start generic documentation -->
523      * Sets the designated parameter to SQL <code>NULL</code>. <p>
524      *
525      * <B>Note:</B> You must specify the parameter's SQL type.<p>
526      * <!-- end generic documentation -->
527      *
528      * <!-- start release-specific documentation -->
529      * <div class="ReleaseSpecificDocumentation">
530      * <h3>HSQLDB-Specific Information:</h3> <p>
531      *
532      * HSQLDB ignores the sqlType argument.
533      * </div>
534      * <!-- end release-specific documentation -->
535      *
536      * @param paramIndex the first parameter is 1, the second is 2, ...
537      * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
538      * @exception SQLException if a database access error occurs
539      */

540     public void setNull(int paramIndex, int sqlType) throws SQLException JavaDoc {
541         setParameter(paramIndex, null);
542     }
543
544     /**
545      * <!-- start generic documentation -->
546      * Sets the designated parameter to the given Java <code>boolean</code>
547      * value. The driver converts this to an SQL <code>BIT</code> value
548      * when it sends it to the database.<p>
549      * <!-- end generic documentation -->
550      *
551      * <!-- start release-specific documentation -->
552      * <div class="ReleaseSpecificDocumentation">
553      * <h3>HSQLDB-Specific Information:</h3> <p>
554      *
555      * Since 1.7.2, HSQLDB uses the BOOLEAN type instead of BIT, as
556      * per SQL 200n (SQL 3).
557      * </div>
558      * <!-- end release-specific documentation -->
559      *
560      * @param parameterIndex the first parameter is 1, the second is 2, ...
561      * @param x the parameter value
562      * @exception SQLException if a database access error occurs
563      */

564     public void setBoolean(int parameterIndex,
565                            boolean x) throws SQLException JavaDoc {
566
567         Boolean JavaDoc b = x ? Boolean.TRUE
568                       : Boolean.FALSE;
569
570         setParameter(parameterIndex, b);
571     }
572
573     /**
574      * <!-- start generic documentation -->
575      * Sets the designated parameter to the given Java <code>byte</code> value.
576      * The driver converts this to an SQL <code>TINYINT</code> value when
577      * it sends it to the database.<p>
578      * <!-- end generic documentation -->
579      *
580      * @param parameterIndex the first parameter is 1, the second is 2, ...
581      * @param x the parameter value
582      * @exception SQLException if a database access error occurs
583      */

584     public void setByte(int parameterIndex, byte x) throws SQLException JavaDoc {
585         setIntParameter(parameterIndex, x);
586     }
587
588     /**
589      * <!-- start generic documentation -->
590      * Sets the designated parameter to the given Java <code>short</code>
591      * value. The driver converts this to an SQL <code>SMALLINT</code>
592      * value when it sends it to the database.<p>
593      * <!-- end generic documentation -->
594      *
595      * @param parameterIndex the first parameter is 1, the second is 2, ...
596      * @param x the parameter value
597      * @exception SQLException if a database access error occurs
598      */

599     public void setShort(int parameterIndex, short x) throws SQLException JavaDoc {
600         setIntParameter(parameterIndex, x);
601     }
602
603     /**
604      * <!-- start generic documentation -->
605      * Sets the designated parameter to the given Java <code>int</code> value.
606      * The driver converts this to an SQL <code>INTEGER</code> value when
607      * it sends it to the database.<p>
608      * <!-- end generic documentation -->
609      *
610      * @param parameterIndex the first parameter is 1, the second is 2, ...
611      * @param x the parameter value
612      * @exception SQLException if a database access error occurs
613      */

614     public void setInt(int parameterIndex, int x) throws SQLException JavaDoc {
615         setIntParameter(parameterIndex, x);
616     }
617
618     /**
619      * <!-- start generic documentation -->
620      * Sets the designated parameter to the given Java <code>long</code> value.
621      * The driver converts this to an SQL <code>BIGINT</code> value when
622      * it sends it to the database.<p>
623      * <!-- end generic documentation -->
624      *
625      * @param parameterIndex the first parameter is 1, the second is 2, ...
626      * @param x the parameter value
627      * @exception SQLException if a database access error occurs
628      */

629     public void setLong(int parameterIndex, long x) throws SQLException JavaDoc {
630         setLongParameter(parameterIndex, x);
631     }
632
633     /**
634      * <!-- start generic documentation -->
635      * Sets the designated parameter to the given Java <code>float</code> value.
636      * The driver converts this to an SQL <code>FLOAT</code> value when
637      * it sends it to the database.<p>
638      * <!-- end generic documentation -->
639      *
640      * <!-- start release-specific documentation -->
641      * <div class="ReleaseSpecificDocumentation">
642      * <h3>HSQLDB-Specific Information:</h3> <p>
643      *
644      * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
645      * and NaN <code>float</code> values consistent with the Java Language
646      * Specification; these <em>special</em> values are now correctly stored
647      * to and retrieved from the database.
648      * </div>
649      * <!-- start release-specific documentation -->
650      *
651      * @param parameterIndex the first parameter is 1, the second is 2, ...
652      * @param x the parameter value
653      * @exception SQLException if a database access error occurs
654      */

655     public void setFloat(int parameterIndex, float x) throws SQLException JavaDoc {
656         setDouble(parameterIndex, (double) x);
657     }
658
659     /**
660      * <!-- start generic documentation -->
661      * Sets the designated parameter to the given Java <code>double</code> value.
662      * The driver converts this to an SQL <code>DOUBLE</code> value when it
663      * sends it to the database.<p>
664      * <!-- end generic documentation -->
665      *
666      * <!-- start release-specific documentation -->
667      * <div class="ReleaseSpecificDocumentation">
668      * <h3>HSQLDB-Specific Information:</h3> <p>
669      *
670      * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
671      * and NaN <code>double</code> values consistent with the Java Language
672      * Specification; these <em>special</em> values are now correctly stored
673      * to and retrieved from the database.
674      * </div>
675      * <!-- start release-specific documentation -->
676      *
677      * @param parameterIndex the first parameter is 1, the second is 2, ...
678      * @param x the parameter value
679      * @exception SQLException if a database access error occurs
680      */

681     public void setDouble(int parameterIndex, double x) throws SQLException JavaDoc {
682
683         Double JavaDoc d = new Double JavaDoc(x);
684
685         setParameter(parameterIndex, d);
686     }
687
688     /**
689      * <!-- start generic documentation -->
690      * Sets the designated parameter to the given
691      * <code>java.math.BigDecimal</code> value.
692      * The driver converts this to an SQL <code>NUMERIC</code> value when
693      * it sends it to the database.<p>
694      * <!-- end generic documentation -->
695      *
696      * @param parameterIndex the first parameter is 1, the second is 2, ...
697      * @param x the parameter value
698      * @exception SQLException if a database access error occurs
699      */

700     public void setBigDecimal(int parameterIndex,
701                               BigDecimal JavaDoc x) throws SQLException JavaDoc {
702         setParameter(parameterIndex, x);
703     }
704
705     /**
706      * <!-- start generic documentation -->
707      * Sets the designated parameter to the given Java <code>String</code> value.
708      * The driver converts this
709      * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
710      * (depending on the argument's
711      * size relative to the driver's limits on <code>VARCHAR</code> values)
712      * when it sends it to the database.<p>
713      * <!-- end generic documentation -->
714      *
715      * <!-- start release-specific documentation -->
716      * <div class="ReleaseSpecificDocumentation">
717      * <h3>HSQLDB-Specific Information:</h3> <p>
718      *
719      * Including 1.7.2, HSQLDB stores all XXXCHAR values as java.lang.String
720      * objects; there is no appreciable difference between
721      * CHAR, VARCHAR and LONGVARCHAR.
722      * </div>
723      * <!-- start release-specific documentation -->
724      *
725      * @param parameterIndex the first parameter is 1, the second is 2, ...
726      * @param x the parameter value
727      * @exception SQLException if a database access error occurs
728      */

729     public void setString(int parameterIndex, String JavaDoc x) throws SQLException JavaDoc {
730         setParameter(parameterIndex, x);
731     }
732
733     /**
734      * <!-- start generic documentation -->
735      * Sets the designated parameter to the given Java array of bytes.
736      * The driver converts this to an SQL <code>VARBINARY</code> or
737      * <code>LONGVARBINARY</code> (depending on the argument's size relative
738      * to the driver's limits on <code>VARBINARY</code> values) when it
739      * sends it to the database.<p>
740      * <!-- end generic documentation -->
741      *
742      * <!-- start release-specific documentation -->
743      * <div class="ReleaseSpecificDocumentation">
744      * <h3>HSQLDB-Specific Information:</h3> <p>
745      *
746      * Including 1.7.2, HSQLDB stores all XXXBINARY values the same way; there
747      * is no appreciable difference between BINARY, VARBINARY and
748      * LONGVARBINARY.
749      * </div>
750      * <!-- start release-specific documentation -->
751      *
752      * @param paramIndex the first parameter is 1, the second is 2, ...
753      * @param x the parameter value
754      * @exception SQLException if a database access error occurs
755      */

756     public void setBytes(int paramIndex, byte[] x) throws SQLException JavaDoc {
757         setParameter(paramIndex, x);
758     }
759
760     /**
761      * <!-- start generic documentation -->
762      * Sets the designated parameter to the given
763      * <code>java.sql.Date</code> value. The driver converts this
764      * to an SQL <code>DATE</code> value when it sends it to the database.<p>
765      * <!-- end generic documentation -->
766      *
767      * @param parameterIndex the first parameter is 1, the second is 2, ...
768      * @param x the parameter value
769      * @exception SQLException if a database access error occurs
770      */

771     public void setDate(int parameterIndex, Date JavaDoc x) throws SQLException JavaDoc {
772         setParameter(parameterIndex, x);
773     }
774
775     /**
776      * <!-- start generic documentation -->
777      * Sets the designated parameter to the given <code>java.sql.Time</code>
778      * value. The driver converts this to an SQL <code>TIME</code> value when it
779      * sends it to the database.<p>
780      * <!-- end generic documentation -->
781      *
782      * @param parameterIndex the first parameter is 1, the second is 2, ...
783      * @param x the parameter value
784      * @exception SQLException if a database access error occurs
785      */

786     public void setTime(int parameterIndex, Time JavaDoc x) throws SQLException JavaDoc {
787         setParameter(parameterIndex, x);
788     }
789
790     /**
791      * <!-- start generic documentation -->
792      * Sets the designated parameter to the given
793      * <code>java.sql.Timestamp</code> value. The driver converts this to
794      * an SQL <code>TIMESTAMP</code> value when it sends it to the
795      * database.<p>
796      * <!-- end generic documentation -->
797      *
798      * @param parameterIndex the first parameter is 1, the second is 2, ...
799      * @param x the parameter value
800      * @exception SQLException if a database access error occurs
801      */

802     public void setTimestamp(int parameterIndex,
803                              Timestamp JavaDoc x) throws SQLException JavaDoc {
804         setParameter(parameterIndex, x);
805     }
806
807     /**
808      * <!-- start generic documentation -->
809      * Sets the designated parameter to the given input stream, which will have
810      * the specified number of bytes.
811      * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
812      * parameter, it may be more practical to send it via a
813      * <code>java.io.InputStream</code>. Data will be read from the stream
814      * as needed until end-of-file is reached. The JDBC driver will
815      * do any necessary conversion from ASCII to the database char format. <p>
816      *
817      * <b>Note:</b> This stream object can either be a standard
818      * Java stream object or your own subclass that implements the
819      * standard interface.<p>
820      * <!-- end generic documentation -->
821      * <!-- start release-specific documentation -->
822      * <div class="ReleaseSpecificDocumentation">
823      * <h3>HSQLDB-Specific Information:</h3> <p>
824      *
825      * This method uses the default platform character encoding to convert bytes
826      * from the stream into the characters of a String. In the future this is
827      * likely to change to always treat the stream as ASCII.<p>
828      *
829      * Before HSQLDB 1.7.0, <code>setAsciiStream</code> and
830      * <code>setUnicodeStream</code> were identical.
831      * </div>
832      * <!-- end release-specific documentation -->
833      *
834      * @param parameterIndex the first parameter is 1, the second is 2, ...
835      * @param x the Java input stream that contains the ASCII parameter value
836      * @param length the number of bytes in the stream
837      * @exception SQLException if a database access error occurs
838      */

839     public void setAsciiStream(int parameterIndex, java.io.InputStream JavaDoc x,
840                                int length) throws SQLException JavaDoc {
841
842         checkSetParameterIndex(parameterIndex, true);
843
844         String JavaDoc s;
845
846         if (x == null) {
847             s = "input stream is null";
848
849             throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, s);
850         }
851
852         try {
853             s = StringConverter.inputStreamToString(x, length);
854
855             setParameter(parameterIndex, s);
856         } catch (IOException JavaDoc e) {
857             throw Util.sqlException(Trace.INVALID_CHARACTER_ENCODING);
858         }
859     }
860
861     /**
862      * <!-- start generic documentation -->
863      * Sets the designated parameter to the given input stream, which
864      * will have the specified number of bytes. A Unicode character has
865      * two bytes, with the first byte being the high byte, and the second
866      * being the low byte.
867      *
868      * When a very large Unicode value is input to a <code>LONGVARCHAR</code>
869      * parameter, it may be more practical to send it via a
870      * <code>java.io.InputStream</code> object. The data will be read from the
871      * stream as needed until end-of-file is reached. The JDBC driver will
872      * do any necessary conversion from Unicode to the database char format.
873      *
874      * <P><B>Note:</B> This stream object can either be a standard
875      * Java stream object or your own subclass that implements the
876      * standard interface.<p>
877      * <!-- end generic documentation -->
878      *
879      * <!-- start release-specific documentation -->
880      * <div class="ReleaseSpecificDocumentation">
881      * <h3>HSQLDB-Specific Information:</h3> <p>
882      *
883      * Since 1.7.0, this method complies with behavior as defined by the
884      * JDBC3 specification.
885      * </div>
886      * <!-- end release-specific documentation -->
887      *
888      * @param parameterIndex the first parameter is 1, the second is 2, ...
889      * @param x a <code>java.io.InputStream</code> object that contains the
890      * Unicode parameter value as two-byte Unicode characters
891      * @param length the number of bytes in the stream
892      * @exception SQLException if a database access error occurs
893      * @deprecated Sun does not include a reason, but presumably
894      * this is because setCharacterStream is now prefered
895      */

896
897 //#ifdef DEPRECATEDJDBC
898
public void setUnicodeStream(int parameterIndex, java.io.InputStream JavaDoc x,
899                                  int length) throws SQLException JavaDoc {
900
901         checkSetParameterIndex(parameterIndex, true);
902
903         String JavaDoc msg = null;
904
905         if (x == null) {
906             msg = "input stream is null";
907         } else if (length % 2 != 0) {
908             msg = "odd length argument";
909         }
910
911         if (msg != null) {
912             throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
913         }
914
915         int chlen = length / 2;
916         int chread = 0;
917         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
918         int hi;
919         int lo;
920
921         try {
922             for (; chread < chlen; chread++) {
923                 hi = x.read();
924
925                 if (hi == -1) {
926                     break;
927                 }
928
929                 lo = x.read();
930
931                 if (lo == -1) {
932                     break;
933                 }
934
935                 sb.append((char) (hi << 8 | lo));
936             }
937         } catch (IOException JavaDoc e) {
938             throw Util.sqlException(Trace.TRANSFER_CORRUPTED);
939         }
940
941         setParameter(parameterIndex, sb.toString());
942     }
943
944 //#endif
945

946     /**
947      * <!-- start generic documentation -->
948      * Sets the designated parameter to the given input stream, which will have
949      * the specified number of bytes.
950      * When a very large binary value is input to a <code>LONGVARBINARY</code>
951      * parameter, it may be more practical to send it via a
952      * <code>java.io.InputStream</code> object. The data will be read from the
953      * stream as needed until end-of-file is reached.
954      *
955      * <P><B>Note:</B> This stream object can either be a standard
956      * Java stream object or your own subclass that implements the
957      * standard interface.<p>
958      * <!-- end generic documentation -->
959      *
960      * <!-- start release-specific documentation -->
961      * <div class="ReleaseSpecificDocumentation">
962      * <h3>HSQLDB-Specific Information:</h3> <p>
963      *
964      * Since 1.7.2, this method works according to the standard.
965      * </div>
966      * <!-- end release-specific documentation -->
967      *
968      * @param parameterIndex the first parameter is 1, the second is 2, ...
969      * @param x the java input stream which contains the binary parameter value
970      * @param length the number of bytes in the stream
971      * @exception SQLException if a database access error occurs
972      */

973     public void setBinaryStream(int parameterIndex, java.io.InputStream JavaDoc x,
974                                 int length) throws SQLException JavaDoc {
975
976         checkSetParameterIndex(parameterIndex, true);
977
978         if (x == null) {
979             throw Util.sqlException(Trace.error(Trace.INVALID_JDBC_ARGUMENT,
980                                                 Trace.JDBC_NULL_STREAM));
981         }
982
983         HsqlByteArrayOutputStream out = null;
984
985         try {
986             out = new HsqlByteArrayOutputStream();
987
988             int size = 2048;
989             byte[] buff = new byte[size];
990
991             for (int left = length; left > 0; ) {
992                 int read = x.read(buff, 0, left > size ? size
993                                                        : left);
994
995                 if (read == -1) {
996                     break;
997                 }
998
999                 out.write(buff, 0, read);
1000
1001                left -= read;
1002            }
1003
1004            setParameter(parameterIndex, out.toByteArray());
1005        } catch (IOException JavaDoc e) {
1006            throw Util.sqlException(Trace.INPUTSTREAM_ERROR, e.toString());
1007        } finally {
1008            if (out != null) {
1009                try {
1010                    out.close();
1011                } catch (IOException JavaDoc e) {}
1012            }
1013        }
1014    }
1015
1016    /**
1017     * <!-- start generic documentation -->
1018     * Clears the current parameter values immediately. <p>
1019     *
1020     * In general, parameter values remain in force for repeated use of a
1021     * statement. Setting a parameter value automatically clears its
1022     * previous value. However, in some cases it is useful to immediately
1023     * release the resources used by the current parameter values; this can
1024     * be done by calling the method <code>clearParameters</code>.<p>
1025     * <!-- end generic documentation -->
1026     *
1027     * @exception SQLException if a database access error occurs
1028     */

1029    public void clearParameters() throws SQLException JavaDoc {
1030
1031        checkClosed();
1032        ArrayUtil.fillArray(parameterValues, null);
1033        ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN, parameterSet, 0,
1034                             parameterSet.length);
1035
1036        if (parameterStream != null) {
1037            ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN,
1038                                 parameterStream, 0, parameterStream.length);
1039        }
1040    }
1041
1042    //----------------------------------------------------------------------
1043
// Advanced features:
1044

1045    /**
1046     * <!-- start generic documentation -->
1047     * Sets the value of the designated parameter with the given object. <p>
1048     *
1049     * The second argument must be an object type; for integral values, the
1050     * <code>java.lang</code> equivalent objects should be used. <p>
1051     *
1052     * The given Java object will be converted to the given targetSqlType
1053     * before being sent to the database.
1054     *
1055     * If the object has a custom mapping (is of a class implementing the
1056     * interface <code>SQLData</code>),
1057     * the JDBC driver should call the method <code>SQLData.writeSQL</code> to
1058     * write it to the SQL data stream.
1059     * If, on the other hand, the object is of a class implementing
1060     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
1061     * <code>Struct</code>, or <code>Array</code>, the driver should pass it
1062     * to the database as a value of the corresponding SQL type. <p>
1063     *
1064     * Note that this method may be used to pass database-specific
1065     * abstract data types.<p>
1066     * <!-- end generic documentation -->
1067     *
1068     * <!-- start release-specific documentation -->
1069     * <div class="ReleaseSpecificDocumentation">
1070     * <h3>HSQLDB-Specific Information:</h3> <p>
1071     *
1072     * Inculding 1.7.1,this method was identical to
1073     * {@link #setObject(int, Object, int) setObject(int, Object, int)}.
1074     * That is, this method simply called setObject(int, Object, int),
1075     * ignoring the scale specification. <p>
1076     *
1077     * Since 1.7.2, this method supports the conversions listed in the
1078     * conversion table B-5 of the JDBC 3 specification. The scale argument
1079     * is not used.
1080     * </div>
1081     * <!-- start release-specific documentation -->
1082     *
1083     * @param parameterIndex the first parameter is 1, the second is 2, ...
1084     * @param x the object containing the input parameter value
1085     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
1086     * sent to the database. The scale argument may further qualify this type.
1087     * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
1088     * this is the number of digits after the decimal point. For all
1089     * other types, this value will be ignored. <p>
1090     *
1091     * Up to and including HSQLDB 1.7.0, this parameter is ignored.
1092     * @exception SQLException if a database access error occurs
1093     * @see java.sql.Types
1094     * @see #setObject(int,Object,int)
1095     */

1096    public void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType,
1097                          int scale) throws SQLException JavaDoc {
1098
1099        /** @todo fredt - implement SQLData support */
1100        setObject(parameterIndex, x);
1101    }
1102
1103    /**
1104     * <!-- start generic documentation -->
1105     * Sets the value of the designated parameter with the given object.
1106     * This method is like the method <code>setObject</code>
1107     * above, except that it assumes a scale of zero. <p>
1108     * <!-- end generic documentation -->
1109     *
1110     * <!-- start release-specific documentation -->
1111     * <div class="ReleaseSpecificDocumentation">
1112     * <h3>HSQLDB-Specific Information:</h3> <p>
1113     *
1114     * Since 1.7.2, this method supports conversions listed in the
1115     * conversion table B-5 of the JDBC 3 specification.
1116     * </div>
1117     * <!-- end release-specific documentation -->
1118     *
1119     * @param parameterIndex the first parameter is 1, the second is 2, ...
1120     * @param x the object containing the input parameter value
1121     * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
1122     * sent to the database
1123     * @exception SQLException if a database access error occurs
1124     * @see #setObject(int,Object)
1125     */

1126    public void setObject(int parameterIndex, Object JavaDoc x,
1127                          int targetSqlType) throws SQLException JavaDoc {
1128        setObject(parameterIndex, x);
1129    }
1130
1131    /**
1132     * <!-- start generic documentation -->
1133     * Sets the value of the designated parameter using the given object. <p>
1134     *
1135     * The second parameter must be of type <code>Object</code>; therefore,
1136     * the <code>java.lang</code> equivalent objects should be used for
1137     * built-in types. <p>
1138     *
1139     * The JDBC specification specifies a standard mapping from
1140     * Java <code>Object</code> types to SQL types. The given argument
1141     * will be converted to the corresponding SQL type before being
1142     * sent to the database. <p>
1143     *
1144     * Note that this method may be used to pass datatabase-
1145     * specific abstract data types, by using a driver-specific Java
1146     * type. If the object is of a class implementing the interface
1147     * <code>SQLData</code>, the JDBC driver should call the method
1148     * <code>SQLData.writeSQL</code> to write it to the SQL data stream.
1149     * If, on the other hand, the object is of a class implementing
1150     * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>,
1151     * <code>Struct</code>, or <code>Array</code>, the driver should pass
1152     * it to the database as a value of the corresponding SQL type. <p>
1153     *
1154     * This method throws an exception if there is an ambiguity, for
1155     * example, if the object is of a class implementing more than one
1156     * of the interfaces named above.<p>
1157     * <!-- end generic documentation -->
1158     *
1159     * <!-- start release-specific documentation -->
1160     * <div class="ReleaseSpecificDocumentation">
1161     * <h3>HSQLDB-Specific Information:</h3><p>
1162     *
1163     * Since 1.7.2, this method supports conversions listed in the conversion
1164     * table B-5 of the JDBC 3 specification.<p>
1165     *
1166     * </div>
1167     *
1168     * @param parameterIndex the first parameter is 1, the second is 2, ...
1169     * @param x the object containing the input parameter value
1170     * @exception SQLException if a database access error occurs or the type
1171     * of the given object is ambiguous
1172     */

1173    public void setObject(int parameterIndex, Object JavaDoc x) throws SQLException JavaDoc {
1174        setParameter(parameterIndex, x);
1175    }
1176
1177    //--------------------------JDBC 2.0-----------------------------
1178

1179    /**
1180     * <!-- start generic documentation -->
1181     * Adds a set of parameters to this <code>PreparedStatement</code>
1182     * object's batch of commands. <p>
1183     * <!-- end generic documentation -->
1184     *
1185     * <!-- start release-specific documentation -->
1186     * <div class="ReleaseSpecificDocumentation">
1187     * <h3>HSQLDB-Specific Information:</h3> <p>
1188     *
1189     * Since 1.7.2, this feature is supported.
1190     * </div>
1191     * <!-- end release-specific documentation -->
1192     *
1193     * @exception SQLException if a database access error occurs
1194     * @see jdbcStatement#addBatch
1195     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1196     * jdbcPreparedStatement)
1197     */

1198// boucherb@users 20030801 - method implemented
1199
public void addBatch() throws SQLException JavaDoc {
1200
1201        checkClosed();
1202
1203        int len = parameterValues.length;
1204        Object JavaDoc[] bpValues = new Object JavaDoc[len];
1205
1206        checkParametersSet();
1207        System.arraycopy(parameterValues, 0, bpValues, 0, len);
1208
1209        if (batchResultOut == null) {
1210            batchResultOut = new Result(ResultConstants.BATCHEXECUTE,
1211                                        parameterTypes, statementID);
1212        }
1213
1214        batchResultOut.add(bpValues);
1215    }
1216
1217    /**
1218     * <!-- start generic documentation -->
1219     * Sets the designated parameter to the given <code>Reader</code>
1220     * object, which is the given number of characters long.
1221     * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
1222     * parameter, it may be more practical to send it via a
1223     * <code>java.io.Reader</code> object. The data will be read from the
1224     * stream as needed until end-of-file is reached. The JDBC driver will
1225     * do any necessary conversion from UNICODE to the database char format.
1226     *
1227     * <P><B>Note:</B> This stream object can either be a standard
1228     * Java stream object or your own subclass that implements the
1229     * standard interface. <p>
1230     * <!-- end generic documentation -->
1231     *
1232     * <!-- start release-specific documentation -->
1233     * <div class="ReleaseSpecificDocumentation">
1234     * <h3>HSQLDB-Specific Information:</h3> <p>
1235     *
1236     * HSQLDB stores CHARACTER and related SQL types as Unicode so
1237     * this method does not perform any conversion.
1238     * </div>
1239     * <!-- end release-specific documentation -->
1240     *
1241     * @param parameterIndex the first parameter is 1, the second is 2, ...
1242     * @param reader the <code>java.io.Reader</code> object that contains the
1243     * Unicode data
1244     * @param length the number of characters in the stream
1245     * @exception SQLException if a database access error occurs
1246     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1247     * jdbcPreparedStatement)
1248     */

1249
1250// fredt@users 20020429 - patch 1.7.0 - method defined
1251
// fredt@users 20020627 - patch 574234 by ohioedge@users
1252
// boucherb@users 20030801 - patch 1.7.2 - updated
1253
public void setCharacterStream(int parameterIndex, java.io.Reader JavaDoc reader,
1254                                   int length) throws SQLException JavaDoc {
1255
1256        checkSetParameterIndex(parameterIndex, true);
1257
1258        if (reader == null) {
1259            String JavaDoc msg = "reader is null";
1260
1261            throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1262        }
1263
1264        final StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1265        final int size = 2048;
1266        final char[] buff = new char[size];
1267
1268        try {
1269            for (int left = length; left > 0; ) {
1270                final int read = reader.read(buff, 0, left > size ? size
1271                                                                  : left);
1272
1273                if (read == -1) {
1274                    break;
1275                }
1276
1277                sb.append(buff, 0, read);
1278
1279                left -= read;
1280            }
1281        } catch (IOException JavaDoc e) {
1282            throw Util.sqlException(Trace.TRANSFER_CORRUPTED, e.toString());
1283        }
1284
1285        setParameter(parameterIndex, sb.toString());
1286    }
1287
1288    /**
1289     * <!-- start generic documentation -->
1290     * Sets the designated parameter to the given
1291     * <code>REF(&lt;structured-type&gt;)</code> value.
1292     * The driver converts this to an SQL <code>REF</code> value when it
1293     * sends it to the database. <p>
1294     * <!-- end generic documentation -->
1295     *
1296     * <!-- start release-specific documentation -->
1297     * <div class="ReleaseSpecificDocumentation">
1298     * <h3>HSQLDB-Specific Information:</h3> <p>
1299     *
1300     * HSQLDB 1.7.2 does not support the SQL REF type. Calling this method
1301     * throws an exception.
1302     *
1303     * </div>
1304     * <!-- end release-specific documentation -->
1305     * @param i the first parameter is 1, the second is 2, ...
1306     * @param x an SQL <code>REF</code> value
1307     * @exception SQLException if a database access error occurs
1308     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1309     * jdbcPreparedStatement)
1310     */

1311    public void setRef(int i, Ref JavaDoc x) throws SQLException JavaDoc {
1312        throw Util.notSupported();
1313    }
1314
1315    /**
1316     * <!-- start generic documentation -->
1317     * Sets the designated parameter to the given <code>Blob</code> object.
1318     * The driver converts this to an SQL <code>BLOB</code> value when it
1319     * sends it to the database. <p>
1320     * <!-- end generic documentation -->
1321     *
1322     * <!-- start release-specific documentation -->
1323     * <div class="ReleaseSpecificDocumentation">
1324     * <h3>HSQLDB-Specific Information:</h3> <p>
1325     *
1326     * Previous to 1.7.2, this feature was not supported. <p>
1327     *
1328     * Since 1.7.2, setBlob is supported. With 1.7.2, setting Blob objects is
1329     * limited to those of length less than or equal to Integer.MAX_VALUE.
1330     * In 1.7.2, setBlob(i,x) is roughly equivalent (null and length handling
1331     * not shown) to:
1332     *
1333     * <pre class="JavaCodeExample">
1334     * <b>setBinaryStream</b>(i, x.<b>getBinaryStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1335     * </pre></div>
1336     * <!-- end release-specific documentation -->
1337     *
1338     * @param i the first parameter is 1, the second is 2, ...
1339     * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code>
1340     * value
1341     * @exception SQLException if a database access error occurs
1342     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1343     * jdbcPreparedStatement)
1344     */

1345
1346// boucherb@users 20030801 - method implemented
1347
//#ifdef JAVA2
1348
public void setBlob(int i, Blob JavaDoc x) throws SQLException JavaDoc {
1349
1350        if (x instanceof jdbcBlob) {
1351            setParameter(i, ((jdbcBlob) x).data);
1352
1353            return;
1354        } else if (x == null) {
1355            setParameter(i, null);
1356
1357            return;
1358        }
1359
1360        checkSetParameterIndex(i, false);
1361
1362        final long length = x.length();
1363
1364        if (length > Integer.MAX_VALUE) {
1365            String JavaDoc msg = "Maximum Blob input octet length exceeded: "
1366                         + length;
1367
1368            throw Util.sqlException(Trace.INPUTSTREAM_ERROR, msg);
1369        }
1370
1371        HsqlByteArrayOutputStream out = null;
1372
1373        try {
1374            out = new HsqlByteArrayOutputStream();
1375
1376            java.io.InputStream JavaDoc in = x.getBinaryStream();
1377            int buffSize = 2048;
1378            byte[] buff = new byte[buffSize];
1379
1380            for (int left = (int) length; left > 0; ) {
1381                int read = in.read(buff, 0, left > buffSize ? buffSize
1382                                                            : left);
1383
1384                if (read == -1) {
1385                    break;
1386                }
1387
1388                out.write(buff, 0, read);
1389
1390                left -= read;
1391            }
1392
1393            setParameter(i, out.toByteArray());
1394        } catch (IOException JavaDoc e) {
1395            throw Util.sqlException(Trace.INPUTSTREAM_ERROR, e.toString());
1396        } finally {
1397            if (out != null) {
1398                try {
1399                    out.close();
1400                } catch (IOException JavaDoc e) {}
1401            }
1402        }
1403    }
1404
1405//#endif JAVA2
1406

1407    /**
1408     * <!-- start generic documentation -->
1409     * Sets the designated parameter to the given <code>Clob</code> object.
1410     * The driver converts this to an SQL <code>CLOB</code> value when it
1411     * sends it to the database. <p>
1412     * <!-- end generic documentation -->
1413     *
1414     * <!-- start release-specific documentation -->
1415     * <div class="ReleaseSpecificDocumentation">
1416     * <h3>HSQLDB-Specific Information:</h3> <p>
1417     *
1418     * Previous to 1.7.2, this feature was not supported. <p>
1419     *
1420     * Since 1.7.2, setClob is supported. With 1.7.2, setting Blob objects is
1421     * limited to those of length less than or equal to Integer.MAX_VALUE.
1422     * In 1.7.2, setClob(i,x) is rougly equivalent (null and length handling
1423     * not shown) to: <p>
1424     *
1425     * <pre class="JavaCodeExample">
1426     * <b>setCharacterStream</b>(i, x.<b>getCharacterStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1427     * </pre></div>
1428     * <!-- end release-specific documentation -->
1429     * @param i the first parameter is 1, the second is 2, ...
1430     * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code>
1431     * value
1432     * @exception SQLException if a database access error occurs
1433     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1434     * jdbcPreparedStatement)
1435     */

1436// boucherb@users 20030801 - method implemented
1437
//#ifdef JAVA2
1438
public void setClob(int i, Clob JavaDoc x) throws SQLException JavaDoc {
1439
1440        if (x instanceof jdbcClob) {
1441            setParameter(i, ((jdbcClob) x).data);
1442
1443            return;
1444        } else if (x == null) {
1445            setParameter(i, null);
1446
1447            return;
1448        }
1449
1450        checkSetParameterIndex(i, false);
1451
1452        final long length = x.length();
1453
1454        if (length > Integer.MAX_VALUE) {
1455            String JavaDoc msg = "Max Clob input character length exceeded: "
1456                         + length;
1457
1458            throw Util.sqlException(Trace.INPUTSTREAM_ERROR, msg);
1459        }
1460
1461        java.io.Reader JavaDoc reader = x.getCharacterStream();
1462        final StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1463        final int size = 2048;
1464        final char[] buff = new char[size];
1465
1466        try {
1467            for (int left = (int) length; left > 0; ) {
1468                final int read = reader.read(buff, 0, left > size ? size
1469                                                                  : left);
1470
1471                if (read == -1) {
1472                    break;
1473                }
1474
1475                sb.append(buff, 0, read);
1476
1477                left -= read;
1478            }
1479        } catch (IOException JavaDoc e) {
1480            throw Util.sqlException(Trace.TRANSFER_CORRUPTED, e.toString());
1481        }
1482
1483        setParameter(i, sb.toString());
1484    }
1485
1486//#endif JAVA2
1487

1488    /**
1489     * <!-- start generic documentation -->
1490     * Sets the designated parameter to the given <code>Array</code> object.
1491     * The driver converts this to an SQL <code>ARRAY</code> value when it
1492     * sends it to the database. <p>
1493     * <!-- end generic documentation -->
1494     *
1495     * <!-- start release-specific documentation -->
1496     * <div class="ReleaseSpecificDocumentation">
1497     * <h3>HSQLDB-Specific Information:</h3> <p>
1498     *
1499     * HSQLDB 1.7.2 does not support the SQL ARRAY type. Calling this method
1500     * throws an exception.
1501     *
1502     * </div>
1503     * <!-- end release-specific documentation -->
1504     * @param i the first parameter is 1, the second is 2, ...
1505     * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code>
1506     * value
1507     * @exception SQLException if a database access error occurs
1508     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1509     * jdbcPreparedStatement)
1510     */

1511    public void setArray(int i, Array JavaDoc x) throws SQLException JavaDoc {
1512        throw Util.notSupported();
1513    }
1514
1515    /**
1516     * <!-- start generic documentation -->
1517     * Retrieves a <code>ResultSetMetaData</code> object that contains
1518     * information about the columns of the <code>ResultSet</code> object
1519     * that will be returned when this <code>PreparedStatement</code> object
1520     * is executed.
1521     * <P>
1522     * Because a <code>PreparedStatement</code> object is precompiled, it is
1523     * possible to know about the <code>ResultSet</code> object that it will
1524     * return without having to execute it. Consequently, it is possible
1525     * to invoke the method <code>getMetaData</code> on a
1526     * <code>PreparedStatement</code> object rather than waiting to execute
1527     * it and then invoking the <code>ResultSet.getMetaData</code> method
1528     * on the <code>ResultSet</code> object that is returned.
1529     * <P>
1530     * <B>NOTE:</B> Using this method may be expensive for some drivers due
1531     * to the lack of underlying DBMS support. <p>
1532     * <!-- end generic documentation -->
1533     *
1534     * <!-- start release-specific documentation -->
1535     * <div class="ReleaseSpecificDocumentation">
1536     * <h3>HSQLDB-Specific Information:</h3> <p>
1537     *
1538     * Since 1.7.2, this feature is supported. If the statement
1539     * generates an update count, then null is returned.
1540     *
1541     * </div>
1542     * <!-- end release-specific documentation -->
1543     * @return the description of a <code>ResultSet</code> object's columns or
1544     * <code>null</code> if the driver cannot return a
1545     * <code>ResultSetMetaData</code> object
1546     * @exception SQLException if a database access error occurs
1547     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1548     * jdbcPreparedStatement)
1549     */

1550
1551// boucherb@users 20030801 - method implemented
1552
public ResultSetMetaData JavaDoc getMetaData() throws SQLException JavaDoc {
1553
1554        checkClosed();
1555
1556        if (isRowCount) {
1557            return null;
1558        }
1559
1560        if (rsmd == null) {
1561            rsmd = new jdbcResultSetMetaData(rsmdDescriptor,
1562                                             connection.connProperties);
1563        }
1564
1565        return rsmd;
1566    }
1567
1568    /**
1569     * <!-- start generic documentation -->
1570     * Sets the designated parameter to the given <code>java.sql.Date</code>
1571     * value, using the given <code>Calendar</code> object. The driver uses
1572     * the <code>Calendar</code> object to construct an SQL <code>DATE</code>
1573     * value,which the driver then sends to the database. With a
1574     * a <code>Calendar</code> object, the driver can calculate the date
1575     * taking into account a custom timezone. If no
1576     * <code>Calendar</code> object is specified, the driver uses the default
1577     * timezone, which is that of the virtual machine running the
1578     * application. <p>
1579     * <!-- end generic documentation -->
1580     *
1581     * @param parameterIndex the first parameter is 1, the second is 2, ...
1582     * @param x the parameter value
1583     * @param cal the <code>Calendar</code> object the driver will use
1584     * to construct the date
1585     * @exception SQLException if a database access error occurs
1586     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1587     * jdbcPreparedStatement)
1588     */

1589
1590// fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1591
// changes by fredt - moved conversion to HsqlDateTime
1592
public void setDate(int parameterIndex, Date JavaDoc x,
1593                        Calendar JavaDoc cal) throws SQLException JavaDoc {
1594
1595        String JavaDoc s;
1596
1597        try {
1598            s = HsqlDateTime.getDateString(x, cal);
1599        } catch (Exception JavaDoc e) {
1600            throw Util.sqlException(Trace.INVALID_ESCAPE, e.toString());
1601        }
1602
1603        setParameter(parameterIndex, s);
1604    }
1605
1606    /**
1607     * <!-- start generic documentation -->
1608     * Sets the designated parameter to the given <code>java.sql.Time</code>
1609     * value, using the given <code>Calendar</code> object. The driver uses
1610     * the <code>Calendar</code> object to construct an SQL <code>TIME</code>
1611     * value, which the driver then sends to the database. With a
1612     * a <code>Calendar</code> object, the driver can calculate the time
1613     * taking into account a custom timezone. If no
1614     * <code>Calendar</code> object is specified, the driver uses the default
1615     * timezone, which is that of the virtual machine running the
1616     * application. <p>
1617     * <!-- end generic documentation -->
1618     *
1619     * @param parameterIndex the first parameter is 1, the second is 2, ...
1620     * @param x the parameter value
1621     * @param cal the <code>Calendar</code> object the driver will use
1622     * to construct the time
1623     * @exception SQLException if a database access error occurs
1624     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1625     * jdbcPreparedStatement)
1626     */

1627
1628// fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1629
// changes by fredt - moved conversion to HsqlDateTime
1630
public void setTime(int parameterIndex, Time JavaDoc x,
1631                        Calendar JavaDoc cal) throws SQLException JavaDoc {
1632
1633        String JavaDoc s;
1634
1635        try {
1636            s = HsqlDateTime.getTimeString(x, cal);
1637        } catch (Exception JavaDoc e) {
1638            throw Util.sqlException(Trace.INVALID_ESCAPE, e.toString());
1639        }
1640
1641        setParameter(parameterIndex, s);
1642    }
1643
1644    /**
1645     * <!-- start generic documentation -->
1646     * Sets the designated parameter to the given <code>java.sql.Timestamp</code>
1647     * value, using the given <code>Calendar</code> object. The driver uses
1648     * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code>
1649     * value, which the driver then sends to the database. With a
1650     * <code>Calendar</code> object, the driver can calculate the timestamp
1651     * taking into account a custom timezone. If no
1652     * <code>Calendar</code> object is specified, the driver uses the default
1653     * timezone, which is that of the virtual machine running the application. <p>
1654     * <!-- end generic documentation -->
1655     *
1656     * @param parameterIndex the first parameter is 1, the second is 2, ...
1657     * @param x the parameter value
1658     * @param cal the <code>Calendar</code> object the driver will use
1659     * to construct the timestamp
1660     * @exception SQLException if a database access error occurs
1661     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1662     * jdbcPreparedStatement)
1663     */

1664
1665// fredt@users 20020414 - patch 517028 by peterhudson@users - method defined
1666
// changes by fredt - moved conversion to HsqlDateTime
1667
public void setTimestamp(int parameterIndex, Timestamp JavaDoc x,
1668                             Calendar JavaDoc cal) throws SQLException JavaDoc {
1669
1670        checkSetParameterIndex(parameterIndex, false);
1671
1672        if (cal != null && x != null) {
1673            int ns = x.getNanos();
1674
1675            x = new Timestamp JavaDoc(HsqlDateTime.getTimeInMillis(x, cal, null));
1676
1677            x.setNanos(ns);
1678        }
1679
1680        setParameter(parameterIndex, x);
1681    }
1682
1683    /**
1684     * <!-- start generic documentation -->
1685     * Sets the designated parameter to SQL <code>NULL</code>.
1686     * This version of the method <code>setNull</code> should
1687     * be used for user-defined types and REF type parameters. Examples
1688     * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
1689     * named array types.
1690     *
1691     * <P><B>Note:</B> To be portable, applications must give the
1692     * SQL type code and the fully-qualified SQL type name when specifying
1693     * a NULL user-defined or REF parameter. In the case of a user-defined
1694     * type the name is the type name of the parameter itself. For a REF
1695     * parameter, the name is the type name of the referenced type. If
1696     * a JDBC driver does not need the type code or type name information,
1697     * it may ignore it.
1698     *
1699     * Although it is intended for user-defined and Ref parameters,
1700     * this method may be used to set a null parameter of any JDBC type.
1701     * If the parameter does not have a user-defined or REF type, the given
1702     * typeName is ignored. <p>
1703     * <!-- end generic documentation -->
1704     *
1705     * <!-- start release-specific documentation -->
1706     * <div class="ReleaseSpecificDocumentation">
1707     * <h3>HSQLDB-Specific Information:</h3> <p>
1708     *
1709     * HSQLDB ignores the sqlType and typeName arguments.
1710     * </div>
1711     * <!-- end release-specific documentation -->
1712     *
1713     * @param paramIndex the first parameter is 1, the second is 2, ...
1714     * @param sqlType a value from <code>java.sql.Types</code>
1715     * @param typeName the fully-qualified name of an SQL user-defined type;
1716     * ignored if the parameter is not a user-defined type or REF
1717     * @exception SQLException if a database access error occurs
1718     * @since JDK 1.2 (JDK 1.1.x developers: read the new overview for
1719     * jdbcPreparedStatement)
1720     */

1721    public void setNull(int paramIndex, int sqlType,
1722                        String JavaDoc typeName) throws SQLException JavaDoc {
1723        setParameter(paramIndex, null);
1724    }
1725
1726    //------------------------- JDBC 3.0 -----------------------------------
1727

1728    /**
1729     * <!-- start generic documentation -->
1730     * Sets the designated parameter to the given <code>java.net.URL</code>
1731     * value. The driver converts this to an SQL <code>DATALINK</code> value
1732     * when it sends it to the database. <p>
1733     * <!-- end generic documentation -->
1734     *
1735     * <!-- start release-specific documentation -->
1736     * <div class="ReleaseSpecificDocumentation">
1737     * <h3>HSQLDB-Specific Information:</h3> <p>
1738     *
1739     * HSQLDB 1.7.2 does not support the DATALINK SQL type for which this
1740     * method is intended. Calling this method throws an exception.
1741     *
1742     * </div>
1743     * <!-- end release-specific documentation -->
1744     * @param parameterIndex the first parameter is 1, the second is 2, ...
1745     * @param x the <code>java.net.URL</code> object to be set
1746     * @exception SQLException if a database access error occurs
1747     * @since JDK 1.4, HSQL 1.7.0
1748     */

1749//#ifdef JDBC3
1750
public void setURL(int parameterIndex,
1751                       java.net.URL JavaDoc x) throws SQLException JavaDoc {
1752        throw Util.notSupported();
1753    }
1754
1755//#endif JDBC3
1756

1757    /**
1758     * <!-- start generic documentation -->
1759     * Retrieves the number, types and properties of this
1760     * <code>PreparedStatement</code> object's parameters. <p>
1761     * <!-- end generic documentation -->
1762     *
1763     * <!-- start release-specific documentation -->
1764     * <div class="ReleaseSpecificDocumentation">
1765     * <h3>HSQLDB-Specific Information:</h3> <p>
1766     *
1767     * Since 1.7.2, this feature is supported.
1768     * </div>
1769     * <!-- end release-specific documentation -->
1770     *
1771     * @return a <code>ParameterMetaData</code> object that contains information
1772     * about the number, types and properties of this
1773     * <code>PreparedStatement</code> object's parameters
1774     * @exception SQLException if a database access error occurs
1775     * @see java.sql.ParameterMetaData
1776     * @since JDK 1.4, HSQL 1.7.0
1777     */

1778// boucherb@users 20030801 - method implemented
1779
//#ifdef JDBC3
1780
public ParameterMetaData JavaDoc getParameterMetaData() throws SQLException JavaDoc {
1781
1782        checkClosed();
1783
1784        if (pmd == null) {
1785            pmd = new jdbcParameterMetaData(pmdDescriptor);
1786        }
1787
1788        // NOTE: pmd is declared as Object to avoid yet another #ifdef.
1789
return (ParameterMetaData JavaDoc) pmd;
1790    }
1791
1792//#endif JDBC3
1793
//-------------------- Internal Implementation -----------------------------
1794

1795    /**
1796     * Constructs a statement that produces results of the requested
1797     * <code>type</code>. <p>
1798     *
1799     * A prepared statement must be a single SQL statement. <p>
1800     *
1801     * @param c the Connection used execute this statement
1802     * @param sql the SQL statement this object represents
1803     * @param type the type of result this statement will produce
1804     * @throws HsqlException if the statement is not accepted by the database
1805     * @throws SQLException if preprocessing by driver fails
1806     */

1807    jdbcPreparedStatement(jdbcConnection c, String JavaDoc sql,
1808                          int type) throws HsqlException, SQLException JavaDoc {
1809
1810        super(c, type);
1811
1812        sql = c.nativeSQL(sql);
1813
1814        resultOut.setResultType(ResultConstants.SQLPREPARE);
1815        resultOut.setMainString(sql);
1816
1817        Result in = connection.sessionProxy.execute(resultOut);
1818
1819        if (in.isError()) {
1820            Util.throwError(in);
1821        }
1822
1823        // else it's a MULTI result encapsulating three sub results:
1824
// 1.) a PREPARE_ACK
1825
//
1826
// Indicates the statement id to be communicated in SQLEXECUTE
1827
// requests to allow the engine to find the corresponding
1828
// CompiledStatement object, parameterize and execute it.
1829
//
1830
// 2.) a description of the statement's result set metadata
1831
//
1832
// This is communicated in the same way as for result sets. That is,
1833
// the metadata arrays of Result, such as colTypes, are used in the
1834
// "conventional" fashion. With some work, it may be possible
1835
// to speed up internal execution of prepared statements by
1836
// dispensing with generating most rsmd values while generating
1837
// the result, safe in the knowlege that the client already
1838
// has a copy of the rsmd. In general, only the colTypes array
1839
// must be available at the engine, and only for network
1840
// communications so that the row output and row input
1841
// interfaces can do their work. One caveat is that the
1842
// columnDisplaySize values are not accurate, as we do
1843
// not consistently enforce column size yet and instead
1844
// approximate the value when a result with actual data is
1845
// retrieved
1846
//
1847
// 3.) a description of the statement's parameter metadata
1848
//
1849
// This is communicated in a similar fashion to 2.), but has
1850
// a slighly different layout to allow the parameter modes
1851
// to be transmitted. The values of this object are used
1852
// to set up the parameter management of this class. The
1853
// object is also used to construct the jdbcParameterMetaData
1854
// object later, if requested. That is, it holds information
1855
// additional to that used by this class, so it should not be
1856
// altered or disposed of
1857
//
1858
// (boucherb@users)
1859
Iterator i;
1860
1861        i = in.iterator();
1862
1863        try {
1864            Object JavaDoc[] row;
1865
1866            // PREPARE_ACK
1867
row = (Object JavaDoc[]) i.next();
1868            statementID = ((Result) row[0]).getStatementID();
1869
1870            // DATA - isParameterDescription == false
1871
row = (Object JavaDoc[]) i.next();
1872            rsmdDescriptor = (Result) row[0];
1873            isRowCount = rsmdDescriptor.mode == ResultConstants.UPDATECOUNT;
1874
1875            // DATA - isParameterDescription == true
1876
row = (Object JavaDoc[]) i.next();
1877            pmdDescriptor = (Result) row[0];
1878            parameterTypes = pmdDescriptor.metaData.getParameterTypes();
1879            parameterValues = new Object JavaDoc[parameterTypes.length];
1880            parameterSet = new boolean[parameterTypes.length];
1881            parameterModes = pmdDescriptor.metaData.paramMode;
1882        } catch (Exception JavaDoc e) {
1883            throw Trace.error(Trace.GENERAL_ERROR, e.toString());
1884        }
1885
1886        resultOut = new Result(ResultConstants.SQLEXECUTE, parameterTypes,
1887                               statementID);
1888
1889        // for toString()
1890
this.sql = sql;
1891    }
1892
1893    /**
1894     * Checks if execution does or does not generate a single row
1895     * update count, throwing if the argument, yes, does not match. <p>
1896     *
1897     * @param yes if true, check that execution generates a single
1898     * row update count, else check that execution generates
1899     * something other than a single row update count.
1900     * @throws SQLException if the argument, yes, does not match
1901     */

1902    protected void checkIsRowCount(boolean yes) throws SQLException JavaDoc {
1903
1904        if (yes != isRowCount) {
1905            int msg = yes ? Trace.JDBC_STATEMENT_NOT_ROW_COUNT
1906                          : Trace.JDBC_STATEMENT_NOT_RESULTSET;
1907
1908            throw Util.sqlException(msg);
1909        }
1910    }
1911
1912    /**
1913     * Checks if the specified parameter index value is valid in terms of
1914     * setting an IN or IN OUT parameter value. <p>
1915     *
1916     * @param i The parameter index to check
1917     * @throws SQLException if the specified parameter index is invalid
1918     */

1919    protected void checkSetParameterIndex(int i,
1920                                          boolean isStream)
1921                                          throws SQLException JavaDoc {
1922
1923        int mode;
1924        String JavaDoc msg;
1925
1926        checkClosed();
1927
1928        if (i < 1 || i > parameterValues.length) {
1929            msg = "parameter index out of range: " + i;
1930
1931            throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1932        }
1933
1934        if (isStream) {
1935            if (parameterStream == null) {
1936                parameterStream = new boolean[parameterTypes.length];
1937            }
1938
1939            parameterStream[i - 1] = true;
1940            parameterSet[i - 1] = false;
1941        } else {
1942            parameterSet[i - 1] = true;
1943        }
1944/*
1945        mode = parameterModes[i - 1];
1946
1947        switch (mode) {
1948
1949            default :
1950                msg = "Not IN or IN OUT mode: " + mode + " for parameter: "
1951                      + i;
1952
1953                throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, msg);
1954            case Expression.PARAM_IN :
1955            case Expression.PARAM_IN_OUT :
1956                break;
1957        }
1958 */

1959    }
1960
1961    /**
1962     * Called just before execution or adding to batch, this ensures all the
1963     * parameters have been set.<p>
1964     *
1965     * If a parameter has been set using a stream method, it should be set
1966     * again for the next reuse. When set using other methods, the parameter
1967     * setting is retained for the next use.
1968     */

1969    private void checkParametersSet() throws SQLException JavaDoc {
1970        ;
1971    }
1972
1973/*
1974    // do not check for compatibility with 1.8.0.x
1975    private void checkParametersSet() throws SQLException {
1976
1977        if (parameterStream == null) {
1978            for (int i = 0; i < parameterSet.length; i++) {
1979                if (!parameterSet[i]) {
1980                    throw Util.sqlException(Trace.JDBC_PARAMETER_NOT_SET);
1981                }
1982            }
1983        } else {
1984            for (int i = 0; i < parameterSet.length; i++) {
1985                if (!parameterSet[i] &&!parameterStream[i]) {
1986                    throw Util.sqlException(Trace.JDBC_PARAMETER_NOT_SET);
1987                }
1988            }
1989
1990            ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_BOOLEAN,
1991                                 parameterStream, 0, parameterStream.length);
1992        }
1993    }
1994*/

1995
1996    /**
1997     * The internal parameter value setter always converts the parameter to
1998     * the Java type required for data transmission. Target BINARY and OTHER
1999     * types are converted directly. All other target types are converted
2000     * by Column.convertObject(). This also normalizes DATETIME values.
2001     *
2002     * @param i parameter index
2003     * @param o object
2004     * @throws SQLException if either argument is not acceptable.
2005     */

2006    private void setParameter(int i, Object JavaDoc o) throws SQLException JavaDoc {
2007
2008        checkSetParameterIndex(i, false);
2009
2010        i--;
2011
2012        if (o == null) {
2013            parameterValues[i] = null;
2014
2015            return;
2016        }
2017
2018        int outType = parameterTypes[i];
2019
2020        try {
2021            switch (outType) {
2022
2023                case Types.OTHER :
2024                    o = new JavaObject((Serializable JavaDoc) o);
2025                    break;
2026
2027                case Types.BINARY :
2028                case Types.VARBINARY :
2029                case Types.LONGVARBINARY :
2030                    if (!(o instanceof byte[])) {
2031                        throw Util.sqlException(
2032                            Trace.error(Trace.INVALID_CONVERSION));
2033                    }
2034
2035                    o = new Binary((byte[]) o, !connection.isNetConn);
2036                    break;
2037
2038                case Types.DATE :
2039                    if (o instanceof java.util.Date JavaDoc) {
2040                        long t = HsqlDateTime.getNormalisedDate(
2041                            ((java.util.Date JavaDoc) o).getTime());
2042
2043                        o = new Date JavaDoc(t);
2044                    } else {
2045                        o = Column.convertObject(o, outType);
2046                    }
2047                    break;
2048
2049                case Types.TIME :
2050                    if (o instanceof java.util.Date JavaDoc) {
2051                        long m = HsqlDateTime.getNormalisedTime(
2052                            ((java.util.Date JavaDoc) o).getTime());
2053
2054                        o = new Time JavaDoc(m);
2055                    } else {
2056                        o = Column.convertObject(o, outType);
2057                    }
2058                    break;
2059
2060                case Types.TIMESTAMP :
2061                    if (o instanceof Timestamp JavaDoc) {
2062                        long m = ((Timestamp JavaDoc) o).getTime();
2063                        int n = ((Timestamp JavaDoc) o).getNanos();
2064
2065                        o = new Timestamp JavaDoc(m);
2066
2067                        ((Timestamp JavaDoc) o).setNanos(n);
2068                    } else {
2069                        o = Column.convertObject(o, outType);
2070                    }
2071                    break;
2072
2073                default :
2074                    o = Column.convertObject(o, outType);
2075                    break;
2076            }
2077        } catch (HsqlException e) {
2078            Util.throwError(e);
2079        }
2080
2081        parameterValues[i] = o;
2082    }
2083
2084    /**
2085     * Used with int and narrower integral primitives
2086     * @param i parameter index
2087     * @param value object to set
2088     * @throws SQLException if either argument is not acceptable
2089     */

2090    private void setIntParameter(int i, int value) throws SQLException JavaDoc {
2091
2092        checkSetParameterIndex(i, false);
2093
2094        int outType = parameterTypes[i - 1];
2095
2096        switch (outType) {
2097
2098            case Types.TINYINT :
2099            case Types.SMALLINT :
2100            case Types.INTEGER :
2101                Object JavaDoc o = new Integer JavaDoc(value);
2102
2103                parameterValues[i - 1] = o;
2104                break;
2105
2106            default :
2107                setLongParameter(i, value);
2108        }
2109    }
2110
2111    /**
2112     * Used with long and narrower integral primitives. Conversion to BINARY
2113     * or OTHER types will throw here and not passed to setParameter().
2114     *
2115     * @param i parameter index
2116     * @param value object to set
2117     * @throws SQLException if either argument is not acceptable
2118     */

2119    private void setLongParameter(int i, long value) throws SQLException JavaDoc {
2120
2121        checkSetParameterIndex(i, false);
2122
2123        int outType = parameterTypes[i - 1];
2124
2125        switch (outType) {
2126
2127            case Types.BIGINT :
2128                Object JavaDoc o = new Long JavaDoc(value);
2129
2130                parameterValues[i - 1] = o;
2131                break;
2132
2133            case Types.BINARY :
2134            case Types.OTHER :
2135                throw Util.sqlException(
2136                    Trace.error(Trace.INVALID_CONVERSION));
2137            default :
2138                setParameter(i, new Long JavaDoc(value));
2139        }
2140    }
2141
2142    /**
2143     * This method should always throw if called for a PreparedStatement or
2144     * CallableStatment.
2145     *
2146     * @param sql ignored
2147     * @throws SQLException always
2148     */

2149    public void addBatch(String JavaDoc sql) throws SQLException JavaDoc {
2150        throw Util.notSupported();
2151    }
2152
2153    /**
2154     * This method should always throw if called for a PreparedStatement or
2155     * CallableStatment.
2156     *
2157     * @param sql ignored
2158     * @throws SQLException always
2159     * @return nothing
2160     */

2161    public ResultSet JavaDoc executeQuery(String JavaDoc sql) throws SQLException JavaDoc {
2162        throw Util.notSupported();
2163    }
2164
2165    /**
2166     * This method should always throw if called for a PreparedStatement or
2167     * CallableStatment.
2168     *
2169     * @param sql ignored
2170     * @throws SQLException always
2171     * @return nothing
2172     */

2173    public boolean execute(String JavaDoc sql) throws SQLException JavaDoc {
2174        throw Util.notSupported();
2175    }
2176
2177    /**
2178     * This method should always throw if called for a PreparedStatement or
2179     * CallableStatment.
2180     *
2181     * @param sql ignored
2182     * @throws SQLException always
2183     * @return nothing
2184     */

2185    public int executeUpdate(String JavaDoc sql) throws SQLException JavaDoc {
2186        throw Util.notSupported();
2187    }
2188
2189    /**
2190     * Does the specialized work required to free this object's resources and
2191     * that of it's parent class. <p>
2192     *
2193     * @throws SQLException if a database access error occurs
2194     */

2195    public synchronized void close() throws SQLException JavaDoc {
2196
2197        if (isClosed()) {
2198            return;
2199        }
2200
2201        HsqlException he = null;
2202
2203        try {
2204
2205            // fredt - if this is called by Connection.close() then there's no
2206
// need to free the prepared statements on the server - it is done
2207
// by Connection.close()
2208
if (!connection.isClosed) {
2209                connection.sessionProxy.execute(
2210                    Result.newFreeStmtRequest(statementID));
2211            }
2212        } catch (HsqlException e) {
2213            he = e;
2214        }
2215
2216        parameterValues = null;
2217        parameterSet = null;
2218        parameterStream = null;
2219        parameterTypes = null;
2220        parameterModes = null;
2221        rsmdDescriptor = null;
2222        pmdDescriptor = null;
2223        rsmd = null;
2224        pmd = null;
2225
2226        super.close();
2227
2228        if (he != null) {
2229            throw Util.sqlException(he);
2230        }
2231    }
2232
2233    /**
2234     * Retrieves a String representation of this object. <p>
2235     *
2236     * The representation is of the form: <p>
2237     *
2238     * class-name@hash[sql=[char-sequence], parameters=[p1, ...pi, ...pn]] <p>
2239     *
2240     * p1, ...pi, ...pn are the String representations of the currently set
2241     * parameter values that will be used with the non-batch execution
2242     * methods. <p>
2243     *
2244     * @return a String representation of this object
2245     */

2246    public String JavaDoc toString() {
2247
2248        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
2249        String JavaDoc sql;
2250        Object JavaDoc[] pv;
2251
2252        sb.append(super.toString());
2253
2254        sql = this.sql;
2255        pv = parameterValues;
2256
2257        if (sql == null || pv == null) {
2258            sb.append("[closed]");
2259
2260            return sb.toString();
2261        }
2262
2263        sb.append("[sql=[").append(sql).append("]");
2264
2265        if (pv.length > 0) {
2266            sb.append(", parameters=[");
2267
2268            for (int i = 0; i < pv.length; i++) {
2269                sb.append('[');
2270                sb.append(pv[i]);
2271                sb.append("], ");
2272            }
2273
2274            sb.setLength(sb.length() - 2);
2275            sb.append(']');
2276        }
2277
2278        sb.append(']');
2279
2280        return sb.toString();
2281    }
2282}
2283
Popular Tags