1 /* Copyright (c) 2001-2016, 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.
operator ""_kind(char p)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;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.io.Reader;
38 import java.io.Serializable;
39 import java.io.StringWriter;
40 import java.math.BigDecimal;
fractional_digits_impl(const char * p)41 import java.sql.Array;
42 import java.sql.BatchUpdateException;
43 import java.sql.Blob;
operator ""_fractional_digits(const char * p)44 import java.sql.Clob;
45 import java.sql.Connection;
46 import java.sql.Date;
streq(const char * p,const char * q)47 import java.sql.ParameterMetaData;
48 import java.sql.PreparedStatement;
49 import java.sql.Ref;
50 import java.sql.ResultSet;
51 import java.sql.ResultSetMetaData;
52 import java.sql.SQLException;
53 import java.sql.SQLWarning;
54 import java.sql.Time;
55 import java.sql.Timestamp;
56 import java.util.ArrayList;
57 import java.util.Calendar;
58 import java.util.UUID;
59
60 //#ifdef JAVA6
61 import java.sql.NClob;
62 import java.sql.RowId;
63 import java.sql.SQLXML;
64
65 //#endif JAVA6
66 import org.hsqldb.HsqlDateTime;
67 import org.hsqldb.HsqlException;
68 import org.hsqldb.SchemaObject;
69 import org.hsqldb.SessionInterface;
70 import org.hsqldb.StatementTypes;
71 import org.hsqldb.error.Error;
72 import org.hsqldb.error.ErrorCode;
73 import org.hsqldb.lib.ArrayUtil;
74 import org.hsqldb.lib.CharArrayWriter;
75 import org.hsqldb.lib.CountdownInputStream;
76 import org.hsqldb.lib.HsqlByteArrayOutputStream;
77 import org.hsqldb.lib.StringConverter;
78 import org.hsqldb.map.ValuePool;
79 import org.hsqldb.navigator.RowSetNavigator;
80 import org.hsqldb.result.Result;
81 import org.hsqldb.result.ResultConstants;
82 import org.hsqldb.result.ResultLob;
83 import org.hsqldb.result.ResultMetaData;
84 import org.hsqldb.result.ResultProperties;
85 import org.hsqldb.types.BinaryData;
86 import org.hsqldb.types.BinaryUUIDType;
87 import org.hsqldb.types.BlobDataID;
88 import org.hsqldb.types.BlobInputStream;
89 import org.hsqldb.types.ClobDataID;
90 import org.hsqldb.types.ClobInputStream;
91 import org.hsqldb.types.DateTimeType;
92 import org.hsqldb.types.JavaObjectData;
93 import org.hsqldb.types.JavaObjectDataInternal;
94 import org.hsqldb.types.TimeData;
95 import org.hsqldb.types.TimestampData;
96 import org.hsqldb.types.Type;
97 import org.hsqldb.types.Types;
98
99 /* $Id: JDBCPreparedStatement.java 5623 2016-05-05 21:03:57Z fredt $ */
100
101 // changes by fredt
102 // SimpleDateFormat objects moved out of methods to improve performance
103 // this is safe because only one thread at a time should access a
104 // PreparedStatement object until it has finished executing the statement
105 //
106 // fredt@users 20020215 - patch 517028 by peterhudson@users - method defined
107 // minor changes by fredt
108 // fredt@users 20020320 - patch 1.7.0 - JDBC 2 support and error trapping;
109 // JDBC 2 methods can now be called from jdk 1.1.x
110 // - see javadoc comments
111 // fredt@users 20020414 - patch 517028 by peterhudson@users - setDate method defined
112 // - setTime method defined
113 // - setTimestamp method defined
114 // changes by fredt - moved conversion to HsqlDateTime
115 // fredt@users 20020429 - patch 1.7.0 - setCharacterStream method defined
mash(unsigned a)116 //
117 // boucherb & 20020409 - extensive review and update of docs and behaviour
118 // fredt@users - 20020505 to comply with previous and latest java.sql specification
119 //
120 // boucherb@users 20020509 - added "throws SQLException" to all methods where it
121 // was missing here but specified in the java.sql.PreparedStatement and
122 // java.sqlCallableStatement interfaces, updated generic documentation to
123 // JDK 1.4, and added JDBC3 methods and docs
124 // fredt@users 20020627 - patch 574234 for setCharacterStream by ohioedge@users
125 // fredt@users 20030620 - patch 1.7.2 - rewritten to support real prepared statements
126 // boucherb@users 20030801 - patch 1.7.2 - support for batch execution
127 // boucherb@users 20030801 - patch 1.7.2 - support for getMetaData and getParameterMetadata
128 // boucherb@users 20030801 - patch 1.7.2 - updated some setXXX methods, incl. setCharacterStream
129 // boucherb@users 20030801 - patch 1.7.2 - setBlob method implemented
130 // boucherb@users 200403/4 - doc 1.7.2 - javadoc updates toward 1.7.2 final
131 // boucherb@users 200403/4 - patch 1.7.2 - eliminate eager buffer allocation from setXXXStream/Blob/Clob
132 // boucherb@users 20051207 - patch 1.8.0.x initial JDBC 4.0 support work
133 // fredt@users 20060215 - patch 1.8.0 - check for unset parameters
134 // fredt@users 20061008 - patch 1.9.0 - partial rewrite with enhancements - separated from jdbcStatement
135 // boucherb@users 20060424 - patch 1.8.x - Mustang Build 81 JDBC 4.0 support
136 // boucherb@users 20060424 - doc 1.9.0 - Full synch up to Mustang Build 84
137 // Revision 1.19 2006/07/12 12:24:17 boucherb
138 // patch 1.9.0
139 // - full synch up to Mustang b90
140
141 /**
142 * <!-- start generic documentation -->
143 *
144 * An object that represents a precompiled SQL statement.
145 * <P>A SQL statement is precompiled and stored in a
146 * <code>PreparedStatement</code> object. This object can then be used to
147 * efficiently execute this statement multiple times.
148 *
149 * <P><B>Note:</B> The setter methods (<code>setShort</code>, <code>setString</code>,
150 * and so on) for setting IN parameter values
151 * must specify types that are compatible with the defined SQL type of
152 * the input parameter. For instance, if the IN parameter has SQL type
153 * <code>INTEGER</code>, then the method <code>setInt</code> should be used.
154 *
155 * <p>If arbitrary parameter type conversions are required, the method
156 * <code>setObject</code> should be used with a target SQL type.
157 * <P>
158 * In the following example of setting a parameter, <code>con</code> represents
159 * an active connection:
160 * <PRE>
161 * PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
162 * SET SALARY = ? WHERE ID = ?");
163 * pstmt.setBigDecimal(1, 153833.00)
164 * pstmt.setInt(2, 110592)
165 * </PRE>
166 *
167 * <!-- end generic documentation -->
168 *
169 * <!-- start Release-specific documentation -->
170 * <div class="ReleaseSpecificDocumentation">
171 * <h3>HSQLDB-Specific Information:</h3> <p>
172 *
173 * From version 2.0, the implementation meets the JDBC specification
174 * requirement that any existing ResultSet is closed when execute() or
175 * executeQuery() methods are called. The connection property close_result=true
176 * is required for this behaviour.
177 * <p>
178 * JDBCPreparedStatement objects are backed by
179 * a true compiled parameteric representation. Hence, there are now significant
180 * performance gains to be had by using a JDBCPreparedStatement object in
181 * preference to a JDBCStatement object when a short-running SQL statement is
182 * to be executed more than once. <p>
183 *
184 * When it can be otherwise avoided, it should be considered poor practice to
185 * fully prepare (construct), parameterize, execute, fetch and close a
186 * JDBCParameterMetaData object for each execution cycle. Indeed,
187 * because the prepare and execute phases
188 * both represent a round-trip to the engine, this practice is likely to be
189 * noticeably <em>less</em> performant for short-running statements (and
190 * possibly even orders of magnitude less performant over network connections
191 * for short-running statements) than the equivalent process using JDBCStatement
192 * objects, albeit far more convenient, less error prone and certainly much
193 * less resource-intensive, especially when large binary and character values
194 * are involved, due to the optimized parameterization facility. <p>
195 *
196 * Instead, when developing an application that is not totally oriented toward
197 * the execution of ad hoc SQL, it is recommended to expend some effort toward
198 * identifying the SQL statements that are good candidates for regular reuse and
199 * adapting the structure of the application accordingly. Often, this is done
200 * by recording the text of candidate SQL statements in an application resource
201 * object (which has the nice side-benefit of isolating and hiding differences
202 * in SQL dialects across different drivers) and caching for possible reuse the
203 * PreparedStatement objects derived from the recorded text. <p>
204 *
205 * Starting with 2.0, when built under a JDBC 4 environment, statement caching
206 * can be transparently enabled or disabled on a statement-by-statement basis by
207 * invoking setPoolable(true | false), respectively, upon Statement objects of
208 * interest. <p>
209 *
210 * <b>Multi thread use:</b> <p>
211 *
212 * A PreparedStatement object is stateful and should not normally be shared
213 * by multiple threads. If it has to be shared, the calls to set the
214 * parameters, calls to add batch statements, the execute call and any
215 * post-execute calls should be made within a block synchronized on the
216 * PreparedStatement Object.<p>
217 *
218 * <b>JRE 1.1.x Notes:</b> <p>
219 *
220 * In general, JDBC 2 support requires Java 1.2 and above, and JDBC3 requires
221 * Java 1.4 and above. In HSQLDB, support for methods introduced in different
222 * versions of JDBC depends on the JDK version used for compiling and building
223 * HSQLDB.<p>
224 *
225 * Since 1.7.0, all JDBC 2 methods can be called while executing under the
226 * version 1.1.x
227 * <em>Java Runtime Environment</em><sup><font size="-2">TM</font></sup>.
228 * However, in addition to this technique requiring explicit casts to the
229 * org.hsqldb.jdbc.* classes, some of these method calls require
230 * <code>int</code> values that are defined only in the JDBC 2 or greater
231 * version of the {@link java.sql.ResultSet ResultSet} interface. For this
232 * reason these values are defined in {@link JDBCResultSet JDBCResultSet}.<p>
233 *
234 * In a JRE 1.1.x environment, calling JDBC 2 methods that take or return the
235 * JDBC2-only <code>ResultSet</code> values can be achieved by referring
236 * to them in parameter specifications and return value comparisons,
237 * respectively, as follows: <p>
238 *
239 * <pre class="JavaCodeExample">
240 * JDBCResultSet.FETCH_FORWARD
241 * JDBCResultSet.TYPE_FORWARD_ONLY
242 * JDBCResultSet.TYPE_SCROLL_INSENSITIVE
243 * JDBCResultSet.CONCUR_READ_ONLY
244 * //etc.
245 * </pre> <p>
246 *
247 * However, please note that code written to use HSQLDB JDBC 2 features under
248 * JDK 1.1.x will not be compatible for use with other JDBC 2 drivers. Please
249 * also note that this feature is offered solely as a convenience to developers
250 * who must work under JDK 1.1.x due to operating constraints, yet wish to
251 * use some of the more advanced features available under the JDBC 2
252 * specification. <p>
253 *
254 * (fredt@users)<br>
255 * (boucherb@users)<p>
256 *
257 * </div>
258 * <!-- end release-specific documentation -->
259 *
260 * @author Campbell Burnet (boucherb@users dot sourceforge.net)
261 * @author Fred Toussi (fredt@users dot sourceforge.net)
262 * @version 2.3.4
263 * @since 1.7.2
264 * @see JDBCConnection#prepareStatement
265 * @see JDBCResultSet
266 */
267 public class JDBCPreparedStatement extends JDBCStatementBase implements PreparedStatement {
268
269 /**
270 * <!-- start generic documentation -->
271 * Executes the SQL query in this <code>PreparedStatement</code> object
272 * and returns the <code>ResultSet</code> object generated by the query.
273 * <!-- end generic documentation -->
274 *
275 * @return a <code>ResultSet</code> object that contains the data produced by the
276 * query; never <code>null</code>
277 * @exception SQLException if a database access error occurs,
278 * this method is called on a closed <code>PreparedStatement</code> or the SQL
279 * statement does not return a <code>ResultSet</code> object
280 */
281 public synchronized ResultSet executeQuery() throws SQLException {
282
283 if (statementRetType != StatementTypes.RETURN_RESULT) {
284 checkStatementType(StatementTypes.RETURN_RESULT);
285 }
286 fetchResult();
287
288 return getResultSet();
289 }
290
291 /**
292 * <!-- start generic documentation -->
293 * Executes the SQL statement in this <code>PreparedStatement</code> object,
294 * (JDBC4 clarification:)
295 * which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
296 * <code>DELETE</code>; or an SQL statement that returns nothing,
297 * such as a DDL statement.
298 * <!-- end generic documentation -->
299 *
300 * @return (JDBC4 clarification:) either (1) the row count for SQL Data Manipulation Language (DML) statements
301 * or (2) 0 for SQL statements that return nothing
302 * @exception SQLException if a database access error occurs,
303 * this method is called on a closed <code>PreparedStatement</code>
304 * or the SQL
305 * statement returns a <code>ResultSet</code> object
306 */
307 public synchronized int executeUpdate() throws SQLException {
308
309 if (statementRetType != StatementTypes.RETURN_COUNT) {
310 checkStatementType(StatementTypes.RETURN_COUNT);
311 }
312 fetchResult();
313
314 return resultIn.getUpdateCount();
315 }
316
317 /**
318 * <!-- start generic documentation -->
319 * Sets the designated parameter to SQL <code>NULL</code>.
320 *
321 * <P><B>Note:</B> You must specify the parameter's SQL type.
322 * <!-- end generic documentation -->
323 *
324 * <!-- start release-specific documentation -->
325 * <div class="ReleaseSpecificDocumentation">
326 * <h3>HSQLDB-Specific Information:</h3> <p>
327 *
328 * HSQLDB currently ignores the sqlType argument.
329 * </div>
330 * <!-- end release-specific documentation -->
331 *
332 * @param parameterIndex the first parameter is 1, the second is 2, ...
333 * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
334 * @exception SQLException if a database access error occurs or
335 * this method is called on a closed <code>PreparedStatement</code>
336 * @exception SQLFeatureNotSupportedException if <code>sqlType</code> is
337 * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
338 * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
339 * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
340 * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
341 * or <code>STRUCT</code> data type and the JDBC driver does not support
342 * this data type
343 */
344 public synchronized void setNull(int parameterIndex,
345 int sqlType) throws SQLException {
346 setParameter(parameterIndex, null);
347 }
348
349 /**
350 * <!-- start generic documentation -->
351 * Sets the designated parameter to the given Java <code>boolean</code> value.
352 * The driver converts this
353 * (JDBC4 Modified:)
354 * to an SQL <code>BIT</code> or <code>BOOLEAN</code> value when it sends it to the database.
355 * <!-- end generic documentation -->
356 *
357 * <!-- start release-specific documentation -->
358 * <div class="ReleaseSpecificDocumentation">
359 * <h3>HSQLDB-Specific Information:</h3> <p>
360 *
361 * HSQLDB supports BOOLEAN type for boolean values. This method can also
362 * be used to set the value of a parameter of the SQL type BIT(1), which is
363 * a bit string consisting of a 0 or 1.
364 * </div>
365 * <!-- end release-specific documentation -->
366 *
367 * @param parameterIndex the first parameter is 1, the second is 2, ...
368 * @param x the parameter value
369 * @exception SQLException if a database access error occurs or
370 * this method is called on a closed <code>PreparedStatement</code>
371 */
372 public synchronized void setBoolean(int parameterIndex,
373 boolean x) throws SQLException {
374
375 Boolean b = x ? Boolean.TRUE
376 : Boolean.FALSE;
377
378 setParameter(parameterIndex, b);
379 }
380
381 /**
382 * <!-- start generic documentation -->
383 * Sets the designated parameter to the given Java <code>byte</code> value.
384 * The driver converts this
385 * to an SQL <code>TINYINT</code> value when it sends it to the database.
386 * <!-- end generic documentation -->
387 *
388 * @param parameterIndex the first parameter is 1, the second is 2, ...
389 * @param x the parameter value
390 * @exception SQLException if a database access error occurs or
391 * this method is called on a closed <code>PreparedStatement</code>
392 */
393 public synchronized void setByte(int parameterIndex,
394 byte x) throws SQLException {
395 setIntParameter(parameterIndex, x);
396 }
397
398 /**
399 * <!-- start generic documentation -->
400 * Sets the designated parameter to the given Java <code>short</code> value.
401 * The driver converts this
402 * to an SQL <code>SMALLINT</code> value when it sends it to the database.
403 * <!-- end generic documentation -->
404 *
405 * @param parameterIndex the first parameter is 1, the second is 2, ...
406 * @param x the parameter value
407 * @exception SQLException if a database access error occurs or
408 * this method is called on a closed <code>PreparedStatement</code>
409 */
410 public synchronized void setShort(int parameterIndex,
411 short x) throws SQLException {
412
413 if (isClosed || connection.isClosed) {
414 checkClosed();
415 }
416 checkSetParameterIndex(parameterIndex);
417
418 if (parameterTypes[parameterIndex - 1].typeCode
419 == Types.SQL_SMALLINT) {
420 parameterValues[--parameterIndex] = Integer.valueOf(x);
421 parameterSet[parameterIndex] = Boolean.TRUE;
422
423 return;
424 }
425 setIntParameter(parameterIndex, x);
426 }
427
428 /**
429 * <!-- start generic documentation -->
430 * Sets the designated parameter to the given Java <code>int</code> value.
431 * The driver converts this
432 * to an SQL <code>INTEGER</code> value when it sends it to the database.
433 * <!-- end generic documentation -->
434 *
435 * @param parameterIndex the first parameter is 1, the second is 2, ...
436 * @param x the parameter value
437 * @exception SQLException if a database access error occurs or
438 * this method is called on a closed <code>PreparedStatement</code>
439 */
440 public synchronized void setInt(int parameterIndex,
441 int x) throws SQLException {
442
443 if (isClosed || connection.isClosed) {
444 checkClosed();
445 }
446 checkSetParameterIndex(parameterIndex);
447
448 if (parameterTypes[parameterIndex - 1].typeCode == Types.SQL_INTEGER) {
449 parameterValues[--parameterIndex] = Integer.valueOf(x);
450 parameterSet[parameterIndex] = Boolean.TRUE;
451
452 return;
453 }
454 setIntParameter(parameterIndex, x);
455 }
456
457 /**
458 * <!-- start generic documentation -->
459 * Sets the designated parameter to the given Java <code>long</code> value.
460 * The driver converts this
461 * to an SQL <code>BIGINT</code> value when it sends it to the database.
462 * <!-- end generic documentation -->
463 *
464 * @param parameterIndex the first parameter is 1, the second is 2, ...
465 * @param x the parameter value
466 * @exception SQLException if a database access error occurs or
467 * this method is called on a closed <code>PreparedStatement</code>
468 */
469 public synchronized void setLong(int parameterIndex,
470 long x) throws SQLException {
471
472 if (isClosed || connection.isClosed) {
473 checkClosed();
474 }
475 checkSetParameterIndex(parameterIndex);
476
477 if (parameterTypes[parameterIndex - 1].typeCode == Types.SQL_BIGINT) {
478 parameterValues[--parameterIndex] = Long.valueOf(x);
479 parameterSet[parameterIndex] = Boolean.TRUE;
480
481 return;
482 }
483 setLongParameter(parameterIndex, x);
484 }
485
486 /**
487 * <!-- start generic documentation -->
488 * Sets the designated parameter to the given Java <code>float</code> value.
489 * The driver converts this
490 * (JDBC4 correction:)
491 * to an SQL <code>REAL</code> value when it sends it to the database.
492 * <!-- end generic documentation -->
493 *
494 * <!-- start release-specific documentation -->
495 * <div class="ReleaseSpecificDocumentation">
496 * <h3>HSQLDB-Specific Information:</h3> <p>
497 *
498 * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
499 * and NaN <code>float</code> values consistent with the Java Language
500 * Specification; these <em>special</em> values are now correctly stored
501 * to and retrieved from the database.
502 * </div>
503 * <!-- start release-specific documentation -->
504 *
505 * @param parameterIndex the first parameter is 1, the second is 2, ...
506 * @param x the parameter value
507 * @exception SQLException if a database access error occurs or
508 * this method is called on a closed <code>PreparedStatement</code>
509 */
510 public synchronized void setFloat(int parameterIndex,
511 float x) throws SQLException {
512 setDouble(parameterIndex, (double) x);
513 }
514
515 /**
516 * <!-- start generic documentation -->
517 * Sets the designated parameter to the given Java <code>double</code> value.
518 * The driver converts this
519 * to an SQL <code>DOUBLE</code> value when it sends it to the database.
520 * <!-- end generic documentation -->
521 *
522 * <!-- start release-specific documentation -->
523 * <div class="ReleaseSpecificDocumentation">
524 * <h3>HSQLDB-Specific Information:</h3> <p>
525 *
526 * Since 1.7.1, HSQLDB handles Java positive/negative Infinity
527 * and NaN <code>double</code> values consistent with the Java Language
528 * Specification; these <em>special</em> values are now correctly stored
529 * to and retrieved from the database.
530 * </div>
531 * <!-- start release-specific documentation -->
532 *
533 * @param parameterIndex the first parameter is 1, the second is 2, ...
534 * @param x the parameter value
535 * @exception SQLException if a database access error occurs or
536 * this method is called on a closed <code>PreparedStatement</code>
537 */
538 public synchronized void setDouble(int parameterIndex,
539 double x) throws SQLException {
540
541 Double d = new Double(x);
542
543 setParameter(parameterIndex, d);
544 }
545
546 /**
547 * <!-- start generic documentation -->
548 * Sets the designated parameter to the given <code>java.math.BigDecimal</code> value.
549 * The driver converts this to an SQL <code>NUMERIC</code> value when
550 * it sends it to the database.
551 * <!-- end generic documentation -->
552 *
553 * @param parameterIndex the first parameter is 1, the second is 2, ...
554 * @param x the parameter value
555 * @exception SQLException if a database access error occurs or
556 * this method is called on a closed <code>PreparedStatement</code>
557 */
558 public synchronized void setBigDecimal(int parameterIndex,
559 BigDecimal x) throws SQLException {
560 setParameter(parameterIndex, x);
561 }
562
563 /**
564 * <!-- start generic documentation -->
565 * Sets the designated parameter to the given Java <code>String</code> value.
566 * The driver converts this
567 * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
568 * (depending on the argument's
569 * size relative to the driver's limits on <code>VARCHAR</code> values)
570 * when it sends it to the database.
571 * <!-- end generic documentation -->
572 *
573 * <!-- start release-specific documentation -->
574 * <div class="ReleaseSpecificDocumentation">
575 * <h3>HSQLDB-Specific Information:</h3> <p>
576 *
577 * Including 2.0, HSQLDB represents all XXXCHAR values internally as
578 * java.lang.String objects; there is no appreciable difference between
579 * CHAR, VARCHAR and LONGVARCHAR.
580 * </div>
581 * <!-- start release-specific documentation -->
582 *
583 * @param parameterIndex the first parameter is 1, the second is 2, ...
584 * @param x the parameter value
585 * @exception SQLException if a database access error occurs or
586 * this method is called on a closed <code>PreparedStatement</code>
587 */
588 public synchronized void setString(int parameterIndex,
589 String x) throws SQLException {
590 setParameter(parameterIndex, x);
591 }
592
593 /**
594 * <!-- start generic documentation -->
595 * Sets the designated parameter to the given Java array of bytes. The driver converts
596 * this to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code>
597 * (depending on the argument's size relative to the driver's limits on
598 * <code>VARBINARY</code> values) when it sends it to the database.
599 * <!-- end generic documentation -->
600 *
601 * <!-- start release-specific documentation -->
602 * <div class="ReleaseSpecificDocumentation">
603 * <h3>HSQLDB-Specific Information:</h3> <p>
604 *
605 * Including 2.0, HSQLDB represents all XXXBINARY values the same way
606 * internally; there is no appreciable difference between BINARY,
607 * VARBINARY and LONGVARBINARY as far as JDBC is concerned.
608 * </div>
609 * <!-- start release-specific documentation -->
610 *
611 * @param parameterIndex the first parameter is 1, the second is 2, ...
612 * @param x the parameter value
613 * @exception SQLException if a database access error occurs or
614 * this method is called on a closed <code>PreparedStatement</code>
615 */
616 public synchronized void setBytes(int parameterIndex,
617 byte[] x) throws SQLException {
618 setParameter(parameterIndex, x);
619 }
620
621 /**
622 * <!-- start generic documentation -->
623 * (JDBC4 clarification:)
624 * Sets the designated parameter to the given <code>java.sql.Date</code> value
625 * using the default time zone of the virtual machine that is running
626 * the application.
627 * The driver converts this
628 * to an SQL <code>DATE</code> value when it sends it to the database.
629 * <!-- end generic documentation -->
630 * <div class="ReleaseSpecificDocumentation">
631 * <h3>HSQLDB-Specific Information:</h3> <p>
632 *
633 * When a setXXX method is used to set a parameter of type
634 * TIMESTAMP WITH TIME ZONE or TIME WITH TIME ZONE the time zone of the
635 * client application is used as time zone
636 * </div>
637 * <!-- end release-specific documentation -->
638 *
639 * @param parameterIndex the first parameter is 1, the second is 2, ...
640 * @param x the parameter value
641 * @exception SQLException if a database access error occurs or
642 * this method is called on a closed <code>PreparedStatement</code>
643 */
644 public synchronized void setDate(int parameterIndex,
645 Date x) throws SQLException {
646 setParameter(parameterIndex, x);
647 }
648
649 /**
650 * <!-- start generic documentation -->
651 * Sets the designated parameter to the given <code>java.sql.Time</code> value.
652 * The driver converts this
653 * to an SQL <code>TIME</code> value when it sends it to the database.
654 * <!-- end generic documentation -->
655 * <div class="ReleaseSpecificDocumentation">
656 * <h3>HSQLDB-Specific Information:</h3> <p>
657 *
658 * When a setXXX method is used to set a parameter of type
659 * TIMESTAMP WITH TIME ZONE or TIME WITH TIME ZONE the time zone of the
660 * client application is used as time zone
661 * </div>
662 * <!-- end release-specific documentation -->
663 *
664 * @param parameterIndex the first parameter is 1, the second is 2, ...
665 * @param x the parameter value
666 * @exception SQLException if a database access error occurs or
667 * this method is called on a closed <code>PreparedStatement</code>
668 */
669 public synchronized void setTime(int parameterIndex,
670 Time x) throws SQLException {
671 setParameter(parameterIndex, x);
672 }
673
674 /**
675 * <!-- start generic documentation -->
676 * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value.
677 * The driver
678 * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
679 * database.
680 * <!-- end generic documentation -->
681 * <div class="ReleaseSpecificDocumentation">
682 * <h3>HSQLDB-Specific Information:</h3> <p>
683 *
684 * When a setXXX method is used to set a parameter of type
685 * TIMESTAMP WITH TIME ZONE or TIME WITH TIME ZONE the time zone of the
686 * client application is used as time zone.<p>
687 *
688 * When this method is used to set a parameter of type TIME or
689 * TIME WITH TIME ZONE, then the nanosecond value of the Timestamp object
690 * will be used if the TIME parameter accepts fractional seconds.
691 * </div>
692 * <!-- end release-specific documentation -->
693 *
694 * @param parameterIndex the first parameter is 1, the second is 2, ...
695 * @param x the parameter value
696 * @exception SQLException if a database access error occurs or
697 * this method is called on a closed <code>PreparedStatement</code>
698 */
699 public synchronized void setTimestamp(int parameterIndex,
700 Timestamp x) throws SQLException {
701 setParameter(parameterIndex, x);
702 }
703
704 /** @todo 1.9.0 - implement streaming */
705
706 /**
707 * <!-- start generic documentation -->
708 * Sets the designated parameter to the given input stream, which will have
709 * the specified number of bytes.
710 * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
711 * parameter, it may be more practical to send it via a
712 * <code>java.io.InputStream</code>. Data will be read from the stream
713 * as needed until end-of-file is reached. The JDBC driver will
714 * do any necessary conversion from ASCII to the database char format.
715 *
716 * <P><B>Note:</B> This stream object can either be a standard
717 * Java stream object or your own subclass that implements the
718 * standard interface.
719 * <!-- end generic documentation -->
720 * <!-- start release-specific documentation -->
721 * <div class="ReleaseSpecificDocumentation">
722 * <h3>HSQLDB-Specific Information:</h3> <p>
723 *
724 * From HSQLDB 2.0 this method uses the US-ASCII character encoding to convert bytes
725 * from the stream into the characters of a String.<p>
726 * This method does not use streaming to send the data,
727 * whether the target is a CLOB or other binary object.<p>
728 *
729 * For long streams (larger than a few megabytes) with CLOB targets,
730 * it is more efficient to use a version of setCharacterStream which takes
731 * the a length parameter.
732 * </div>
733 * <!-- end release-specific documentation -->
734 *
735 * @param parameterIndex the first parameter is 1, the second is 2, ...
736 * @param x the Java input stream that contains the ASCII parameter value
737 * @param length the number of bytes in the stream
738 * @exception SQLException if a database access error occurs or
739 * this method is called on a closed <code>PreparedStatement</code>
740 */
741 public synchronized void setAsciiStream(int parameterIndex,
742 java.io.InputStream x, int length) throws SQLException {
743 setAsciiStream(parameterIndex, x, (long) length);
744 }
745
746 /**
747 * <!-- start generic documentation -->
748 * Sets the designated parameter to the given input stream, which
749 * will have the specified number of bytes.
750 * (JDBC4 deleted:)
751 * [A Unicode character has two bytes, with the first byte being the high
752 * byte, and the second being the low byte.] <p>
753 *
754 * When a very large Unicode value is input to a <code>LONGVARCHAR</code>
755 * parameter, it may be more practical to send it via a
756 * <code>java.io.InputStream</code> object. The data will be read from the
757 * stream as needed until end-of-file is reached. The JDBC driver will
758 * do any necessary conversion from Unicode to the database char format.
759 *
760 * (JDBC4 added:)
761 * The byte format of the Unicode stream must be a Java UTF-8, as defined in the
762 * Java Virtual Machine Specification.
763 *
764 * <P><B>Note:</B> This stream object can either be a standard
765 * Java stream object or your own subclass that implements the
766 * standard interface.
767 * <!-- end generic documentation -->
768 *
769 * <!-- start release-specific documentation -->
770 * <div class="ReleaseSpecificDocumentation">
771 * <h3>HSQLDB-Specific Information:</h3> <p>
772 *
773 * From 1.7.0 to 1.8.0.x, this method complies with behavior as defined by
774 * the JDBC3 specification (the stream is treated as though it has UTF16
775 * encoding). <p>
776 *
777 * Starting with 2.0, this method behaves according to the JDBC4
778 * specification (the stream is treated as though it has UTF-8
779 * encoding, as defined in the Java Virtual Machine Specification) when
780 * built under JDK 1.6+; otherwise, it behaves as defined by the JDBC3
781 * specification. Regardless, this method is deprecated: please use
782 * setCharacterStream(...) instead.
783 * </div>
784 * <!-- end release-specific documentation -->
785 *
786 * @param parameterIndex the first parameter is 1, the second is 2, ...
787 * @param x a <code>java.io.InputStream</code> object that contains the
788 * Unicode parameter value
789 * (JDBC4 deleted:)
790 * [as two-byte Unicode characters]
791 * @param length the number of bytes in the stream
792 * @exception SQLException if a database access error occurs or
793 * this method is called on a closed <code>PreparedStatement</code>
794 * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
795 * this method
796 * @deprecated
797 * Sun does not include a reason, but presumably
798 * this is because setCharacterStream is now preferred
799 */
800
801 //#ifdef DEPRECATEDJDBC
802 public synchronized void setUnicodeStream(int parameterIndex,
803 java.io.InputStream x, int length) throws SQLException {
804
805 checkSetParameterIndex(parameterIndex);
806
807 String msg = null;
808 final int ver = JDBCDatabaseMetaData.JDBC_MAJOR;
809
810 if (x == null) {
811 throw JDBCUtil.nullArgument("x");
812 }
813
814 // CHECKME: Is JDBC4 clarification of UNICODE stream format retroactive?
815 if ((ver < 4) && (length % 2 != 0)) {
816 msg = "Odd length argument for UTF16 encoded stream: " + length;
817
818 throw JDBCUtil.invalidArgument(msg);
819 }
820
821 String encoding = (ver < 4) ? "UTF16"
822 : "UTF8";
823 StringWriter writer = new StringWriter();
824
825 try {
826 CountdownInputStream cis = new CountdownInputStream(x);
827 InputStreamReader reader = new InputStreamReader(cis, encoding);
828 char[] buff = new char[1024];
829 int charsRead;
830
831 cis.setCount(length);
832
833 while (-1 != (charsRead = reader.read(buff))) {
834 writer.write(buff, 0, charsRead);
835 }
836 } catch (IOException ex) {
837 throw JDBCUtil.sqlException(ErrorCode.SERVER_TRANSFER_CORRUPTED,
838 ex.toString(), ex);
839 }
840 setParameter(parameterIndex, writer.toString());
841 }
842
843 //#endif
844
845 /** @todo 1.9.0 - implement streaming */
846
847 /**
848 * <!-- start generic documentation -->
849 * Sets the designated parameter to the given input stream, which will have
850 * the specified number of bytes.
851 * When a very large binary value is input to a <code>LONGVARBINARY</code>
852 * parameter, it may be more practical to send it via a
853 * <code>java.io.InputStream</code> object. The data will be read from the
854 * stream as needed until end-of-file is reached.
855 *
856 * <P><B>Note:</B> This stream object can either be a standard
857 * Java stream object or your own subclass that implements the
858 * standard interface.
859 * <!-- end generic documentation -->
860 *
861 * <!-- start release-specific documentation -->
862 * <div class="ReleaseSpecificDocumentation">
863 * <h3>HSQLDB-Specific Information:</h3> <p>
864 *
865 * Since 1.7.2, this method works according to the standard.
866 * </div>
867 * <!-- end release-specific documentation -->
868 *
869 * @param parameterIndex the first parameter is 1, the second is 2, ...
870 * @param x the java input stream which contains the binary parameter value
871 * @param length the number of bytes in the stream
872 * @exception SQLException if a database access error occurs or
873 * this method is called on a closed <code>PreparedStatement</code>
874 */
875 public synchronized void setBinaryStream(int parameterIndex,
876 java.io.InputStream x, int length) throws SQLException {
877 setBinaryStream(parameterIndex, x, (long) length);
878 }
879
880 /**
881 * <!-- start generic documentation -->
882 * Clears the current parameter values immediately.
883 * <P>In general, parameter values remain in force for repeated use of a
884 * statement. Setting a parameter value automatically clears its
885 * previous value. However, in some cases it is useful to immediately
886 * release the resources used by the current parameter values; this can
887 * be done by calling the method <code>clearParameters</code>.
888 * <!-- end generic documentation -->
889 *
890 * @exception SQLException if a database access error occurs or
891 * this method is called on a closed <code>PreparedStatement</code>
892 */
893 public synchronized void clearParameters() throws SQLException {
894
895 if (isClosed || connection.isClosed) {
896 checkClosed();
897 }
898 ArrayUtil.fillArray(parameterValues, null);
899 ArrayUtil.fillArray(parameterSet, null);
900 ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_LONG, streamLengths, 0,
901 streamLengths.length);
902 }
903
904 //----------------------------------------------------------------------
905 // Advanced features:
906
907 /**
908 * <p>Sets the value of the designated parameter with the given object. The second
909 * argument must be an object type; for integral values, the
910 * <code>java.lang</code> equivalent objects should be used.
911 *
912 * If the second argument is an <code>InputStream</code> then the stream must contain
913 * the number of bytes specified by scaleOrLength. If the second argument is a
914 * <code>Reader</code> then the reader must contain the number of characters specified
915 * by scaleOrLength. If these conditions are not true the driver will generate a
916 * <code>SQLException</code> when the prepared statement is executed.
917 *
918 * <p>The given Java object will be converted to the given targetSqlType
919 * before being sent to the database.
920 *
921 * If the object has a custom mapping (is of a class implementing the
922 * interface <code>SQLData</code>),
923 * the JDBC driver should call the method <code>SQLData.writeSQL</code> to
924 * write it to the SQL data stream.
925 * If, on the other hand, the object is of a class implementing
926 * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>, <code>NClob</code>,
927 * <code>Struct</code>, <code>java.net.URL</code>,
928 * or <code>Array</code>, the driver should pass it to the database as a
929 * value of the corresponding SQL type.
930 *
931 * <p>Note that this method may be used to pass database-specific
932 * abstract data types.
933 *
934 * @param parameterIndex the first parameter is 1, the second is 2, ...
935 * @param x the object containing the input parameter value
936 * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
937 * sent to the database. The scale argument may further qualify this type.
938 * @param scaleOrLength for <code>java.sql.Types.DECIMAL</code>
939 * or <code>java.sql.Types.NUMERIC types</code>,
940 * this is the number of digits after the decimal point. For
941 * Java Object types <code>InputStream</code> and <code>Reader</code>,
942 * this is the length
943 * of the data in the stream or reader. For all other types,
944 * this value will be ignored.
945 * @exception SQLException if a database access error occurs,
946 * this method is called on a closed <code>PreparedStatement</code> or
947 * if the Java Object specified by x is an InputStream
948 * or Reader object and the value of the scale parameter is less
949 * than zero
950 * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
951 * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
952 * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
953 * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
954 * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
955 * or <code>STRUCT</code> data type and the JDBC driver does not support
956 * this data type
957 * @see java.sql.Types
958 */
959 public synchronized void setObject(int parameterIndex, Object x,
960 int targetSqlType,
961 int scaleOrLength) throws SQLException {
962
963 if (x instanceof InputStream) {
964 setBinaryStream(parameterIndex, (InputStream) x, scaleOrLength);
965 } else if (x instanceof Reader) {
966 setCharacterStream(parameterIndex, (Reader) x, scaleOrLength);
967 } else {
968 setObject(parameterIndex, x);
969 }
970 }
971
972 /**
973 * <!-- start generic documentation -->
974 * Sets the value of the designated parameter with the given object.
975 * This method is like the method <code>setObject</code>
976 * above, except that it assumes a scale of zero.
977 * <!-- end generic documentation -->
978 *
979 * <!-- start release-specific documentation -->
980 * <div class="ReleaseSpecificDocumentation">
981 * <h3>HSQLDB-Specific Information:</h3> <p>
982 *
983 * Since 1.7.2, this method supports conversions listed in the
984 * conversion table B-5 of the JDBC 3 specification.
985 * </div>
986 * <!-- end release-specific documentation -->
987 *
988 * @param parameterIndex the first parameter is 1, the second is 2, ...
989 * @param x the object containing the input parameter value
990 * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
991 * sent to the database
992 * @exception SQLException if a database access error occurs or
993 * this method is called on a closed <code>PreparedStatement</code>
994 * @exception SQLFeatureNotSupportedException if <code>targetSqlType</code> is
995 * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
996 * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
997 * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
998 * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
999 * or <code>STRUCT</code> data type and the JDBC driver does not support
1000 * this data type
1001 * @see #setObject(int,Object)
1002 */
1003 public synchronized void setObject(int parameterIndex, Object x,
1004 int targetSqlType) throws SQLException {
1005 setObject(parameterIndex, x);
1006 }
1007
1008 /**
1009 * <!-- start generic documentation -->
1010 * <p>Sets the value of the designated parameter using the given object.
1011 * The second parameter must be of type <code>Object</code>; therefore, the
1012 * <code>java.lang</code> equivalent objects should be used for built-in types.
1013 *
1014 * <p>The JDBC specification specifies a standard mapping from
1015 * Java <code>Object</code> types to SQL types. The given argument
1016 * will be converted to the corresponding SQL type before being
1017 * sent to the database.
1018 *
1019 * <p>Note that this method may be used to pass database-
1020 * specific abstract data types, by using a driver-specific Java
1021 * type.
1022 *
1023 * If the object is of a class implementing the interface <code>SQLData</code>,
1024 * the JDBC driver should call the method <code>SQLData.writeSQL</code>
1025 * to write it to the SQL data stream.
1026 * If, on the other hand, the object is of a class implementing
1027 * <code>Ref</code>, <code>Blob</code>, <code>Clob</code>, (JDBC4 new:) [ <code>NClob</code> ],
1028 * <code>Struct</code>, <code>java.net.URL</code>, (JDBC4 new:) [ <code>RowId</code>, <code>SQLXML</code> ]
1029 * or <code>Array</code>, the driver should pass it to the database as a
1030 * value of the corresponding SQL type.
1031 * <P>
1032 * <b>Note:</b> Not all databases allow for a non-typed Null to be sent to
1033 * the backend. For maximum portability, the <code>setNull</code> or the
1034 * <code>setObject(int parameterIndex, Object x, int sqlType)</code>
1035 * method should be used
1036 * instead of <code>setObject(int parameterIndex, Object x)</code>.
1037 * <p>
1038 * <b>Note:</b> This method throws an exception if there is an ambiguity, for example, if the
1039 * object is of a class implementing more than one of the interfaces named above.
1040 * <!-- end generic documentation -->
1041 *
1042 * <!-- start release-specific documentation -->
1043 * <div class="ReleaseSpecificDocumentation">
1044 * <h3>HSQLDB-Specific Information:</h3><p>
1045 *
1046 * Since 1.7.2, this method supports conversions listed in the conversion
1047 * table B-5 of the JDBC 3 specification.
1048 * </div>
1049 *
1050 * @param parameterIndex the first parameter is 1, the second is 2, ...
1051 * @param x the object containing the input parameter value
1052 * @exception SQLException if a database access error occurs,
1053 * this method is called on a closed <code>PreparedStatement</code>
1054 * or the type of the given object is ambiguous
1055 */
1056 public synchronized void setObject(int parameterIndex,
1057 Object x) throws SQLException {
1058 setParameter(parameterIndex, x);
1059 }
1060
1061 /**
1062 * <!-- start generic documentation -->
1063 * Executes the SQL statement in this <code>PreparedStatement</code> object,
1064 * which may be any kind of SQL statement.
1065 * Some prepared statements return multiple results; the <code>execute</code>
1066 * method handles these complex statements as well as the simpler
1067 * form of statements handled by the methods <code>executeQuery</code>
1068 * and <code>executeUpdate</code>.
1069 * <P>
1070 * The <code>execute</code> method returns a <code>boolean</code> to
1071 * indicate the form of the first result. You must call either the method
1072 * <code>getResultSet</code> or <code>getUpdateCount</code>
1073 * to retrieve the result; you must call <code>getMoreResults</code> to
1074 * move to any subsequent result(s).
1075 * <!-- end generic documentation -->
1076 *
1077 * <!-- start release-specific documentation -->
1078 * <div class="ReleaseSpecificDocumentation">
1079 * <h3>HSQLDB-Specific Information:</h3> <p>
1080 *
1081 * If the statement is a call to a PROCEDURE, it may return multiple
1082 * multiple fetchable results. <p>
1083 *
1084 * </div>
1085 *
1086 * @return <code>true</code> if the first result is a <code>ResultSet</code>
1087 * object; <code>false</code> if the first result is an update
1088 * count or there is no result
1089 * @exception SQLException if a database access error occurs,
1090 * this method is called on a closed <code>PreparedStatement</code>
1091 * or an argument is supplied to this method
1092 * @see JDBCStatement#execute
1093 * @see JDBCStatement#getResultSet
1094 * @see JDBCStatement#getUpdateCount
1095 * @see JDBCStatement#getMoreResults
1096 *
1097 */
1098 public synchronized boolean execute() throws SQLException {
1099
1100 fetchResult();
1101
1102 return statementRetType == StatementTypes.RETURN_RESULT;
1103 }
1104
1105 //--------------------------JDBC 2.0-----------------------------
1106
1107 /**
1108 * <!-- start generic documentation -->
1109 * Adds a set of parameters to this <code>PreparedStatement</code>
1110 * object's batch of commands.
1111 * <!-- end generic documentation -->
1112 *
1113 * <!-- start release-specific documentation -->
1114 * <div class="ReleaseSpecificDocumentation">
1115 * <h3>HSQLDB-Specific Information:</h3> <p>
1116 *
1117 * Since 1.7.2, this feature is supported.
1118 * </div>
1119 * <!-- end release-specific documentation -->
1120 *
1121 * @exception SQLException if a database access error occurs or
1122 * this method is called on a closed <code>PreparedStatement</code>
1123 * @see JDBCStatement#addBatch
1124 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1125 * JDBCParameterMetaData)
1126 */
1127 public synchronized void addBatch() throws SQLException {
1128
1129 if (isClosed || connection.isClosed) {
1130 checkClosed();
1131 }
1132 checkParametersSet();
1133
1134 if (!isBatch) {
1135 resultOut.setBatchedPreparedExecuteRequest();
1136
1137 isBatch = true;
1138 }
1139
1140 try {
1141 performPreExecute();
1142 } catch (HsqlException e) {
1143 throw JDBCUtil.sqlException(e);
1144 }
1145
1146 int len = parameterValues.length;
1147 Object[] batchParamValues = new Object[len];
1148
1149 System.arraycopy(parameterValues, 0, batchParamValues, 0, len);
1150 resultOut.addBatchedPreparedExecuteRequest(batchParamValues);
1151 }
1152
1153 /** @todo 1.9.0 - implement streaming */
1154
1155 /**
1156 * <!-- start generic documentation -->
1157 * Sets the designated parameter to the given <code>Reader</code>
1158 * object, which is the given number of characters long.
1159 * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
1160 * parameter, it may be more practical to send it via a
1161 * <code>java.io.Reader</code> object. The data will be read from the stream
1162 * as needed until end-of-file is reached. The JDBC driver will
1163 * do any necessary conversion from UNICODE to the database char format.
1164 *
1165 * <P><B>Note:</B> This stream object can either be a standard
1166 * Java stream object or your own subclass that implements the
1167 * standard interface.
1168 * <!-- end generic documentation -->
1169 *
1170 * <!-- start release-specific documentation -->
1171 * <div class="ReleaseSpecificDocumentation">
1172 * <h3>HSQLDB-Specific Information:</h3> <p>
1173 *
1174 * From HSQLDB 2.0 this method uses streaming to send data
1175 * when the target is a CLOB.<p>
1176 * HSQLDB represents CHARACTER and related SQL types as UTF16 Unicode
1177 * internally, so this method does not perform any conversion.
1178 * </div>
1179 * <!-- end release-specific documentation -->
1180 *
1181 * @param parameterIndex the first parameter is 1, the second is 2, ...
1182 * @param reader the <code>java.io.Reader</code> object that contains the
1183 * Unicode data
1184 * @param length the number of characters in the stream
1185 * @exception SQLException if a database access error occurs or
1186 * this method is called on a closed <code>PreparedStatement</code>
1187 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1188 * JDBCParameterMetaData)
1189 */
1190 public synchronized void setCharacterStream(int parameterIndex,
1191 java.io.Reader reader, int length) throws SQLException {
1192 setCharacterStream(parameterIndex, reader, (long) length);
1193 }
1194
1195 /**
1196 * <!-- start generic documentation -->
1197 * Sets the designated parameter to the given
1198 * <code>REF(<structured-type>)</code> value.
1199 * The driver converts this to an SQL <code>REF</code> value when it
1200 * sends it to the database.
1201 * <!-- end generic documentation -->
1202 *
1203 * <!-- start release-specific documentation -->
1204 * <div class="ReleaseSpecificDocumentation">
1205 * <h3>HSQLDB-Specific Information:</h3> <p>
1206 *
1207 * Including 2.0 HSQLDB does not support the SQL REF type. Calling this method
1208 * throws an exception.
1209 *
1210 * </div>
1211 * <!-- end release-specific documentation -->
1212 * @param parameterIndex the first parameter is 1, the second is 2, ...
1213 * @param x an SQL <code>REF</code> value
1214 * @exception SQLException if a database access error occurs or
1215 * this method is called on a closed <code>PreparedStatement</code>
1216 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
1217 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1218 * JDBCParameterMetaData)
1219 */
1220 public void setRef(int parameterIndex, Ref x) throws SQLException {
1221 throw JDBCUtil.notSupported();
1222 }
1223
1224 /**
1225 * <!-- start generic documentation -->
1226 * Sets the designated parameter to the given <code>java.sql.Blob</code> object.
1227 * The driver converts this to an SQL <code>BLOB</code> value when it
1228 * sends it to the database.
1229 * <!-- end generic documentation -->
1230 *
1231 * <!-- start release-specific documentation -->
1232 * <div class="ReleaseSpecificDocumentation">
1233 * <h3>HSQLDB-Specific Information:</h3> <p>
1234 *
1235 * For parameters of type Blob, setBlob works normally.<p>
1236 *
1237 * In addition since 1.7.2, setBlob is supported for BINARY and VARBINARY
1238 * parameters. In this context, the Blob object is
1239 * hard-limited to those of length less than or equal to Integer.MAX_VALUE.
1240 * In practice, soft limits such as available heap and maximum disk usage
1241 * per file (such as the transaction log) dictate a much smaller maximum
1242 * length. <p>
1243 *
1244 * For BINARY and VARBINARY parameter types setBlob(i,x) is roughly
1245 * equivalent (null and length handling not shown) to:<p>
1246 *
1247 * <pre class="JavaCodeExample">
1248 * <b>setBinaryStream</b>(i, x.<b>getBinaryStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1249 * </pre></div>
1250 * <!-- end release-specific documentation -->
1251 *
1252 * @param parameterIndex the first parameter is 1, the second is 2, ...
1253 * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
1254 * @exception SQLException if a database access error occurs or
1255 * this method is called on a closed <code>PreparedStatement</code>
1256 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
1257 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1258 * JDBCParameterMetaData)
1259 */
1260 public synchronized void setBlob(int parameterIndex,
1261 Blob x) throws SQLException {
1262
1263 checkSetParameterIndex(parameterIndex);
1264
1265 Type outType = parameterTypes[parameterIndex - 1];
1266
1267 switch (outType.typeCode) {
1268
1269 case Types.SQL_BINARY :
1270 case Types.SQL_VARBINARY :
1271 setBlobForBinaryParameter(parameterIndex, x);
1272
1273 return;
1274 case Types.SQL_BLOB :
1275 setBlobParameter(parameterIndex, x);
1276
1277 break;
1278 default :
1279 throw JDBCUtil.invalidArgument();
1280 }
1281 }
1282
1283 /**
1284 * Converts a blob to binary data for non-blob binary parameters.
1285 */
1286 private void setBlobForBinaryParameter(int parameterIndex,
1287 Blob x) throws SQLException {
1288
1289 if (x instanceof JDBCBlob) {
1290 setParameter(parameterIndex, ((JDBCBlob) x).data());
1291
1292 return;
1293 } else if (x == null) {
1294 setParameter(parameterIndex, null);
1295
1296 return;
1297 }
1298
1299 final long length = x.length();
1300
1301 if (length > Integer.MAX_VALUE) {
1302 String msg = "Maximum Blob input octet length exceeded: " + length; // NOI18N
1303
1304 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR, msg);
1305 }
1306
1307 try {
1308 java.io.InputStream in = x.getBinaryStream();
1309 HsqlByteArrayOutputStream out = new HsqlByteArrayOutputStream(in,
1310 (int) length);
1311
1312 setParameter(parameterIndex, out.toByteArray());
1313 out.close();
1314 } catch (Throwable e) {
1315 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR,
1316 e.toString(), e);
1317 }
1318 }
1319
1320 /**
1321 * <!-- start generic documentation -->
1322 * Sets the designated parameter to the given <code>java.sql.Clob</code> object.
1323 * The driver converts this to an SQL <code>CLOB</code> value when it
1324 * sends it to the database.
1325 * <!-- end generic documentation -->
1326 *
1327 * <!-- start release-specific documentation -->
1328 * <div class="ReleaseSpecificDocumentation">
1329 * <h3>HSQLDB-Specific Information:</h3> <p>
1330 *
1331 * For parameters of type Clob, setClob works normally.<p>
1332 *
1333 * In addition since 1.7.2, setClob is supported for CHARACTER and VARCHAR
1334 * parameters. In this context, the Clob object is
1335 * hard-limited to those of length less than or equal to Integer.MAX_VALUE.
1336 * In practice, soft limits such as available heap and maximum disk usage
1337 * per file (such as the transaction log) dictate a much smaller maximum
1338 * length. <p>
1339 *
1340 * For CHARACTER and VARCHAR parameter types setClob(i,x) is roughly
1341 * equivalent (null and length handling not shown) to:<p>
1342 *
1343 * <pre class="JavaCodeExample">
1344 * <b>setCharacterStream</b>(i, x.<b>getCharacterStream</b>(), (<span class="JavaKeyWord">int</span>) x.<b>length</b>());
1345 * </pre></div>
1346 * <!-- end release-specific documentation -->
1347 * @param parameterIndex the first parameter is 1, the second is 2, ...
1348 * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
1349 * @exception SQLException if a database access error occurs or
1350 * this method is called on a closed <code>PreparedStatement</code>
1351 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
1352 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1353 * JDBCParameterMetaData)
1354 */
1355 public synchronized void setClob(int parameterIndex,
1356 Clob x) throws SQLException {
1357
1358 checkSetParameterIndex(parameterIndex);
1359
1360 Type outType = parameterTypes[parameterIndex - 1];
1361
1362 switch (outType.typeCode) {
1363
1364 case Types.SQL_CHAR :
1365 case Types.SQL_VARCHAR :
1366 setClobForStringParameter(parameterIndex, x);
1367
1368 return;
1369 case Types.SQL_CLOB :
1370 setClobParameter(parameterIndex, x);
1371
1372 return;
1373 default :
1374 throw JDBCUtil.invalidArgument();
1375 }
1376 }
1377
1378 private void setClobForStringParameter(int parameterIndex,
1379 Clob x) throws SQLException {
1380
1381 if (x instanceof JDBCClob) {
1382 setParameter(parameterIndex, ((JDBCClob) x).data());
1383
1384 return;
1385 } else if (x == null) {
1386 setParameter(parameterIndex, null);
1387
1388 return;
1389 }
1390
1391 final long length = x.length();
1392
1393 if (length > Integer.MAX_VALUE) {
1394 String msg = "Max Clob input character length exceeded: " + length; // NOI18N
1395
1396 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR, msg);
1397 }
1398
1399 try {
1400 java.io.Reader reader = x.getCharacterStream();
1401 CharArrayWriter writer = new CharArrayWriter(reader, (int) length);
1402
1403 setParameter(parameterIndex, writer.toString());
1404 } catch (Throwable e) {
1405 throw JDBCUtil.sqlException(ErrorCode.SERVER_TRANSFER_CORRUPTED,
1406 e.toString(), e);
1407 }
1408 }
1409
1410 /**
1411 * <!-- start generic documentation -->
1412 * Sets the designated parameter to the given <code>java.sql.Array</code> object.
1413 * The driver converts this to an SQL <code>ARRAY</code> value when it
1414 * sends it to the database.
1415 * <!-- end generic documentation -->
1416 *
1417 * <!-- start release-specific documentation -->
1418 * <div class="ReleaseSpecificDocumentation">
1419 * <h3>HSQLDB-Specific Information:</h3> <p>
1420 *
1421 * From version 2.0, HSQLDB supports the SQL ARRAY type.
1422 *
1423 * </div>
1424 * <!-- end release-specific documentation -->
1425 *
1426 * @param parameterIndex the first parameter is 1, the second is 2, ...
1427 * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code> value
1428 * @exception SQLException if a database access error occurs or
1429 * this method is called on a closed <code>PreparedStatement</code>
1430 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
1431 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1432 * JDBCParameterMetaData)
1433 */
1434 public synchronized void setArray(int parameterIndex,
1435 Array x) throws SQLException {
1436
1437 checkParameterIndex(parameterIndex);
1438
1439 Type type = this.parameterMetaData.columnTypes[parameterIndex - 1];
1440
1441 if (!type.isArrayType()) {
1442 throw JDBCUtil.sqlException(ErrorCode.X_42561);
1443 }
1444
1445 if (x == null) {
1446 setParameter(parameterIndex, null);
1447
1448 return;
1449 }
1450
1451 Object[] data = null;
1452
1453 if (x instanceof JDBCArray) {
1454 data = ((JDBCArray) x).getArrayInternal();
1455 } else {
1456 Object object = x.getArray();
1457
1458 if (object instanceof Object[]) {
1459 Type baseType = type.collectionBaseType();
1460 Object[] array = (Object[]) object;
1461
1462 data = new Object[array.length];
1463
1464 for (int i = 0; i < data.length; i++) {
1465 data[i] = baseType.convertJavaToSQL(session, array[i]);
1466 }
1467 } else {
1468
1469 // if foreign data is not Object[]
1470 throw JDBCUtil.notSupported();
1471 }
1472 }
1473 parameterValues[parameterIndex - 1] = data;
1474 parameterSet[parameterIndex - 1] = Boolean.TRUE;
1475 }
1476
1477 /**
1478 * <!-- start generic documentation -->
1479 * Retrieves a <code>ResultSetMetaData</code> object that contains
1480 * information about the columns of the <code>ResultSet</code> object
1481 * that will be returned when this <code>PreparedStatement</code> object
1482 * is executed.
1483 * <P>
1484 * Because a <code>PreparedStatement</code> object is pre-compiled, it is
1485 * possible to know about the <code>ResultSet</code> object that it will
1486 * return without having to execute it. Consequently, it is possible
1487 * to invoke the method <code>getMetaData</code> on a
1488 * <code>PreparedStatement</code> object rather than waiting to execute
1489 * it and then invoking the <code>ResultSet.getMetaData</code> method
1490 * on the <code>ResultSet</code> object that is returned.
1491 * <P>
1492 * <B>NOTE:</B> Using this method may be expensive for some drivers due
1493 * to the lack of underlying DBMS support.
1494 * <!-- end generic documentation -->
1495 *
1496 * <!-- start release-specific documentation -->
1497 * <div class="ReleaseSpecificDocumentation">
1498 * <h3>HSQLDB-Specific Information:</h3> <p>
1499 *
1500 * Since 1.7.2, this feature is supported and is <em>inexpensive</em> as
1501 * it is backed by underlying DBMS support. If the statement
1502 * generates an update count, then null is returned.
1503 * </div>
1504 * <!-- end release-specific documentation -->
1505 * @return the description of a <code>ResultSet</code> object's columns or
1506 * <code>null</code> if the driver cannot return a
1507 * <code>ResultSetMetaData</code> object
1508 * @exception SQLException if a database access error occurs or
1509 * this method is called on a closed <code>PreparedStatement</code>
1510 * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
1511 * this method
1512 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1513 * JDBCParameterMetaData)
1514 */
1515 public synchronized ResultSetMetaData getMetaData() throws SQLException {
1516
1517 if (isClosed || connection.isClosed) {
1518 checkClosed();
1519 }
1520
1521 if (statementRetType != StatementTypes.RETURN_RESULT) {
1522 return null;
1523 }
1524
1525 if (resultSetMetaData == null) {
1526 boolean isUpdatable = ResultProperties.isUpdatable(rsProperties);
1527 boolean isInsertable = isUpdatable;
1528
1529 if (isInsertable) {
1530 for (int i = 0; i < resultMetaData.colIndexes.length; i++) {
1531 if (resultMetaData.colIndexes[i] < 0) {
1532 isInsertable = false;
1533
1534 break;
1535 }
1536 }
1537 }
1538 resultSetMetaData = new JDBCResultSetMetaData(resultMetaData,
1539 isUpdatable, isInsertable, connection);
1540 }
1541
1542 return resultSetMetaData;
1543 }
1544
1545 /**
1546 * <!-- start generic documentation -->
1547 * Sets the designated parameter to the given <code>java.sql.Date</code> value,
1548 * using the given <code>Calendar</code> object. The driver uses
1549 * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
1550 * which the driver then sends to the database. With
1551 * a <code>Calendar</code> object, the driver can calculate the date
1552 * taking into account a custom timezone. If no
1553 * <code>Calendar</code> object is specified, the driver uses the default
1554 * timezone, which is that of the virtual machine running the application.
1555 * <!-- end generic documentation -->
1556 *
1557 * @param parameterIndex the first parameter is 1, the second is 2, ...
1558 * @param x the parameter value
1559 * @param cal the <code>Calendar</code> object the driver will use
1560 * to construct the date
1561 * @exception SQLException if a database access error occurs or
1562 * this method is called on a closed <code>PreparedStatement</code>
1563 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1564 * JDBCParameterMetaData)
1565 */
1566 public synchronized void setDate(int parameterIndex, Date x,
1567 Calendar cal) throws SQLException {
1568
1569 checkSetParameterIndex(parameterIndex);
1570
1571 int i = parameterIndex - 1;
1572
1573 if (x == null) {
1574 parameterValues[i] = null;
1575 parameterSet[i] = Boolean.TRUE;
1576
1577 return;
1578 }
1579
1580 Type outType = parameterTypes[i];
1581 Calendar calendar = cal == null ? session.getCalendar()
1582 : cal;
1583
1584 long millis = HsqlDateTime.convertMillisFromCalendar(
1585 session.getCalendarGMT(), calendar, x.getTime());
1586
1587 millis = HsqlDateTime.getNormalisedDate(session.getCalendarGMT(),
1588 millis);
1589
1590 switch (outType.typeCode) {
1591
1592 case Types.SQL_DATE :
1593 case Types.SQL_TIMESTAMP :
1594 parameterValues[i] = new TimestampData(millis / 1000);
1595
1596 break;
1597 case Types.SQL_TIMESTAMP_WITH_TIME_ZONE :
1598 int zoneOffset = HsqlDateTime.getZoneMillis(calendar, millis);
1599
1600 parameterValues[i] = new TimestampData(millis / 1000, 0,
1601 zoneOffset / 1000);
1602
1603 break;
1604 default :
1605 throw JDBCUtil.sqlException(ErrorCode.X_42561);
1606 }
1607 parameterSet[i] = Boolean.TRUE;
1608 }
1609
1610 /**
1611 * <!-- start generic documentation -->
1612 * Sets the designated parameter to the given <code>java.sql.Time</code> value,
1613 * using the given <code>Calendar</code> object. The driver uses
1614 * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
1615 * which the driver then sends to the database. With
1616 * a <code>Calendar</code> object, the driver can calculate the time
1617 * taking into account a custom timezone. If no
1618 * <code>Calendar</code> object is specified, the driver uses the default
1619 * timezone, which is that of the virtual machine running the application.
1620 * <!-- end generic documentation -->
1621 * <div class="ReleaseSpecificDocumentation">
1622 * <h3>HSQLDB-Specific Information:</h3> <p>
1623 *
1624 * When a setXXX method is used to set a parameter of type
1625 * TIMESTAMP WITH TIME ZONE or TIME WITH TIME ZONE the time zone (including
1626 * Daylight Saving Time) of the Calendar is used as time zone for the
1627 * value.<p>
1628 *
1629 * </div>
1630 * <!-- end release-specific documentation -->
1631 *
1632 * @param parameterIndex the first parameter is 1, the second is 2, ...
1633 * @param x the parameter value
1634 * @param cal the <code>Calendar</code> object the driver will use
1635 * to construct the time
1636 * @exception SQLException if a database access error occurs or
1637 * this method is called on a closed <code>PreparedStatement</code>
1638 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1639 * JDBCParameterMetaData)
1640 */
1641 public synchronized void setTime(int parameterIndex, Time x,
1642 Calendar cal) throws SQLException {
1643
1644 checkSetParameterIndex(parameterIndex);
1645
1646 int i = parameterIndex - 1;
1647
1648 if (x == null) {
1649 parameterValues[i] = null;
1650 parameterSet[i] = Boolean.TRUE;
1651
1652 return;
1653 }
1654
1655 Type outType = parameterTypes[i];
1656 long millis = x.getTime();
1657 int zoneOffset = 0;
1658 Calendar calendar = cal == null ? session.getCalendar()
1659 : cal;
1660
1661 millis = HsqlDateTime.convertMillisFromCalendar(
1662 session.getCalendarGMT(), calendar, millis);
1663 millis = HsqlDateTime.convertToNormalisedTime(millis,
1664 session.getCalendarGMT());
1665
1666 switch (outType.typeCode) {
1667
1668 case Types.SQL_TIME :
1669 break;
1670 case Types.SQL_TIME_WITH_TIME_ZONE :
1671 zoneOffset = HsqlDateTime.getZoneMillis(calendar, millis);
1672
1673 break;
1674 default :
1675 throw JDBCUtil.sqlException(ErrorCode.X_42561);
1676 }
1677 parameterValues[i] = new TimeData((int) (millis / 1000), 0,
1678 zoneOffset / 1000);
1679 parameterSet[i] = Boolean.TRUE;
1680 }
1681
1682 /**
1683 * <!-- start generic documentation -->
1684 * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
1685 * using the given <code>Calendar</code> object. The driver uses
1686 * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
1687 * which the driver then sends to the database. With a
1688 * <code>Calendar</code> object, the driver can calculate the timestamp
1689 * taking into account a custom timezone. If no
1690 * <code>Calendar</code> object is specified, the driver uses the default
1691 * timezone, which is that of the virtual machine running the application.
1692 * <!-- end generic documentation -->
1693 * <div class="ReleaseSpecificDocumentation">
1694 * <h3>HSQLDB-Specific Information:</h3> <p>
1695 *
1696 * When a setXXX method is used to set a parameter of type
1697 * TIMESTAMP WITH TIME ZONE or TIME WITH TIME ZONE the time zone (including
1698 * Daylight Saving Time) of the Calendar is used as time zone.<p>
1699 * In this case, if the Calendar argument is null, then the default Calendar
1700 * for the clients JVM is used as the Calendar<p>
1701 *
1702 * When this method is used to set a parameter of type TIME or
1703 * TIME WITH TIME ZONE, then the nanosecond value of the Timestamp object
1704 * is used if the TIME parameter accepts fractional seconds.<p>
1705 *
1706 * </div>
1707 * <!-- end release-specific documentation -->
1708 *
1709 * @param parameterIndex the first parameter is 1, the second is 2, ...
1710 * @param x the parameter value
1711 * @param cal the <code>Calendar</code> object the driver will use
1712 * to construct the timestamp
1713 * @exception SQLException if a database access error occurs or
1714 * this method is called on a closed <code>PreparedStatement</code>
1715 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1716 * JDBCParameterMetaData)
1717 */
1718 public synchronized void setTimestamp(int parameterIndex, Timestamp x,
1719 Calendar cal) throws SQLException {
1720
1721 checkSetParameterIndex(parameterIndex);
1722
1723 int i = parameterIndex - 1;
1724
1725 if (x == null) {
1726 parameterValues[i] = null;
1727 parameterSet[i] = Boolean.TRUE;
1728
1729 return;
1730 }
1731
1732 Type outType = parameterTypes[i];
1733 long millis = x.getTime();
1734 long seconds;
1735 int zoneOffset = 0;
1736 Calendar calendar = cal == null ? session.getCalendar()
1737 : cal;
1738
1739 millis = HsqlDateTime.convertMillisFromCalendar(
1740 session.getCalendarGMT(),calendar, millis);
1741 switch (outType.typeCode) {
1742
1743 case Types.SQL_TIMESTAMP_WITH_TIME_ZONE :
1744 zoneOffset = HsqlDateTime.getZoneMillis(calendar, millis);
1745
1746 // fall through
1747 case Types.SQL_TIMESTAMP :
1748 seconds = millis / 1000;
1749 if (seconds < DateTimeType.epochSeconds
1750 || seconds > DateTimeType.limitSeconds) {
1751 throw Error.error(ErrorCode.X_22008);
1752 }
1753 parameterValues[i] = new TimestampData(seconds,
1754 x.getNanos(), zoneOffset / 1000);
1755
1756 break;
1757 case Types.SQL_TIME :
1758 millis = HsqlDateTime.getNormalisedTime(
1759 session.getCalendarGMT(), millis);
1760 parameterValues[i] = new TimeData((int) (millis / 1000),
1761 x.getNanos(), 0);
1762
1763 break;
1764 case Types.SQL_TIME_WITH_TIME_ZONE :
1765 millis = HsqlDateTime.getNormalisedTime(
1766 session.getCalendarGMT(), millis);
1767 zoneOffset = HsqlDateTime.getZoneMillis(calendar, millis);
1768 parameterValues[i] = new TimeData((int) (millis / 1000),
1769 x.getNanos(), zoneOffset / 1000);
1770
1771 break;
1772 case Types.SQL_DATE :
1773 millis = HsqlDateTime.getNormalisedDate(
1774 session.getCalendarGMT(), millis);
1775 seconds = millis / 1000;
1776
1777 if (seconds < DateTimeType.epochSeconds
1778 || seconds > DateTimeType.limitSeconds) {
1779 throw Error.error(ErrorCode.X_22008);
1780 }
1781
1782 parameterValues[i] = new TimestampData(seconds);
1783
1784 break;
1785 default :
1786 throw JDBCUtil.sqlException(ErrorCode.X_42561);
1787 }
1788 parameterSet[i] = Boolean.TRUE;
1789 }
1790
1791 /**
1792 * <!-- start generic documentation -->
1793 * Sets the designated parameter to SQL <code>NULL</code>.
1794 * This version of the method <code>setNull</code> should
1795 * be used for user-defined types and REF type parameters. Examples
1796 * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
1797 * named array types.
1798 *
1799 * <P><B>Note:</B> To be portable, applications must give the
1800 * SQL type code and the fully-qualified SQL type name when specifying
1801 * a NULL user-defined or REF parameter. In the case of a user-defined type
1802 * the name is the type name of the parameter itself. For a REF
1803 * parameter, the name is the type name of the referenced type. If
1804 * a JDBC driver does not need the type code or type name information,
1805 * it may ignore it.
1806 *
1807 * Although it is intended for user-defined and Ref parameters,
1808 * this method may be used to set a null parameter of any JDBC type.
1809 * If the parameter does not have a user-defined or REF type, the given
1810 * typeName is ignored.
1811 *
1812 * <!-- end generic documentation -->
1813 *
1814 * <!-- start release-specific documentation -->
1815 * <div class="ReleaseSpecificDocumentation">
1816 * <h3>HSQLDB-Specific Information:</h3> <p>
1817 *
1818 * HSQLDB simply ignores the sqlType and typeName arguments.
1819 * </div>
1820 * <!-- end release-specific documentation -->
1821 *
1822 * @param parameterIndex the first parameter is 1, the second is 2, ...
1823 * @param sqlType a value from <code>java.sql.Types</code>
1824 * @param typeName the fully-qualified name of an SQL user-defined type;
1825 * ignored if the parameter is not a user-defined type or REF
1826 * @exception SQLException if a database access error occurs or
1827 * this method is called on a closed <code>PreparedStatement</code>
1828 * @exception SQLFeatureNotSupportedException if <code>sqlType</code> is
1829 * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
1830 * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
1831 * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
1832 * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
1833 * or <code>STRUCT</code> data type and the JDBC driver does not support
1834 * this data type or if the JDBC driver does not support this method
1835 * @since JDK 1.2 (JDK 1.1.x developers: read the overview for
1836 * JDBCParameterMetaData)
1837 */
1838 public synchronized void setNull(int parameterIndex, int sqlType,
1839 String typeName) throws SQLException {
1840 setParameter(parameterIndex, null);
1841 }
1842
1843 //------------------------- JDBC 2.0 - overriden methods -------------------
1844
1845 /**
1846 * <!-- start generic documentation -->
1847 * Submits a batch of commands to the database for execution and
1848 * if all commands execute successfully, returns an array of update counts.
1849 * The <code>int</code> elements of the array that is returned are ordered
1850 * to correspond to the commands in the batch, which are ordered
1851 * according to the order in which they were added to the batch.
1852 * The elements in the array returned by the method <code>executeBatch</code>
1853 * may be one of the following:
1854 * <OL>
1855 * <LI>A number greater than or equal to zero -- indicates that the
1856 * command was processed successfully and is an update count giving the
1857 * number of rows in the database that were affected by the command's
1858 * execution
1859 * <LI>A value of <code>SUCCESS_NO_INFO</code> -- indicates that the command was
1860 * processed successfully but that the number of rows affected is
1861 * unknown
1862 * <P>
1863 * If one of the commands in a batch update fails to execute properly,
1864 * this method throws a <code>BatchUpdateException</code>, and a JDBC
1865 * driver may or may not continue to process the remaining commands in
1866 * the batch. However, the driver's behavior must be consistent with a
1867 * particular DBMS, either always continuing to process commands or never
1868 * continuing to process commands. If the driver continues processing
1869 * after a failure, the array returned by the method
1870 * <code>BatchUpdateException.getUpdateCounts</code>
1871 * will contain as many elements as there are commands in the batch, and
1872 * at least one of the elements will be the following:
1873 * <P>
1874 * <LI>A value of <code>EXECUTE_FAILED</code> -- indicates that the command failed
1875 * to execute successfully and occurs only if a driver continues to
1876 * process commands after a command fails
1877 * </OL>
1878 * <P>
1879 * A driver is not required to implement this method.
1880 * The possible implementations and return values have been modified in
1881 * the Java 2 SDK, Standard Edition, version 1.3 to
1882 * accommodate the option of continuing to proccess commands in a batch
1883 * update after a <code>BatchUpdateException</code> object has been thrown. <p>
1884 * <!-- end generic documentation -->
1885 *
1886 * <!-- start release-specific documentation -->
1887 * <div class="ReleaseSpecificDocumentation">
1888 * <h3>HSQLDB-Specific Information:</h3> <p>
1889 *
1890 * Starting with HSQLDB 1.7.2, this feature is supported. <p>
1891 *
1892 * HSQLDB stops execution of commands in a batch when one of the commands
1893 * results in an exception. The size of the returned array equals the
1894 * number of commands that were executed successfully.<p>
1895 *
1896 * </div>
1897 * <!-- end release-specific documentation -->
1898 *
1899 * @return an array of update counts containing one element for each
1900 * command in the batch. The elements of the array are ordered according
1901 * to the order in which commands were added to the batch.
1902 * @exception SQLException if a database access error occurs,
1903 * this method is called on a closed <code>Statement</code> or the
1904 * driver does not support batch statements. Throws {@link BatchUpdateException}
1905 * (a subclass of <code>SQLException</code>) if one of the commands sent to the
1906 * database fails to execute properly or attempts to return a result set.
1907 *
1908 *
1909 * @see #addBatch
1910 * @see java.sql.DatabaseMetaData#supportsBatchUpdates()
1911 * @since JDK 1.3 (JDK 1.1.x developers: read the overview for
1912 * JDBCStatement)
1913 */
1914 public synchronized int[] executeBatch() throws SQLException {
1915
1916 if (isClosed || connection.isClosed) {
1917 checkClosed();
1918 }
1919 checkStatementType(StatementTypes.RETURN_COUNT);
1920
1921 if (!isBatch) {
1922 if (connection.isEmptyBatchAllowed) {
1923 return ValuePool.emptyIntArray;
1924 }
1925
1926 throw JDBCUtil.sqlExceptionSQL(ErrorCode.X_07506);
1927 }
1928 generatedResult = null;
1929
1930 int batchCount = resultOut.getNavigator().getSize();
1931
1932 resultIn = null;
1933
1934 try {
1935 resultIn = session.execute(resultOut);
1936 } catch (HsqlException e) {
1937 throw JDBCUtil.sqlException(e);
1938 } finally {
1939 performPostExecute();
1940 resultOut.getNavigator().clear();
1941
1942 isBatch = false;
1943 }
1944
1945 if (resultIn.mode == ResultConstants.ERROR) {
1946 throw JDBCUtil.sqlException(resultIn);
1947 }
1948
1949 RowSetNavigator navigator = resultIn.getNavigator();
1950 int[] updateCounts = new int[navigator.getSize()];
1951
1952 for (int i = 0; i < updateCounts.length; i++) {
1953 Object[] data = navigator.getNext();
1954
1955 updateCounts[i] = ((Integer) data[0]).intValue();
1956 }
1957
1958 if (updateCounts.length != batchCount) {
1959 if (errorResult == null) {
1960 throw new BatchUpdateException(updateCounts);
1961 } else {
1962 throw new BatchUpdateException(errorResult.getMainString(),
1963 errorResult.getSubString(),
1964 errorResult.getErrorCode(), updateCounts);
1965 }
1966 }
1967
1968 return updateCounts;
1969 }
1970
1971 /**
1972 * <!-- start generic documentation -->
1973 * Sets escape processing on or off. <p>
1974 * <!-- end generic documentation -->
1975 *
1976 * <!-- start release-specific documentation -->
1977 * <div class="ReleaseSpecificDocumentation">
1978 * <h3>HSQLDB-Specific Information:</h3> <p>
1979 *
1980 * As per JDBC spec, calling this method has no effect.
1981 * </div>
1982 * <!-- end release-specific documentation -->
1983 *
1984 * @param enable <code>true</code> to enable escape processing;
1985 * <code>false</code> to disable it
1986 * @exception SQLException if a database access error occurs
1987 */
1988 public void setEscapeProcessing(boolean enable) throws SQLException {
1989 checkClosed();
1990 }
1991
1992 /**
1993 * This method should always throw if called for a PreparedStatement or
1994 * CallableStatement.
1995 *
1996 * @param sql ignored
1997 * @throws SQLException always
1998 */
1999 public void addBatch(String sql) throws SQLException {
2000 throw JDBCUtil.notSupported();
2001 }
2002
2003 /**
2004 * This method should always throw if called for a PreparedStatement or
2005 * CallableStatement.
2006 *
2007 * @param sql ignored
2008 * @throws SQLException always
2009 * @return nothing
2010 */
2011 public synchronized ResultSet executeQuery(
2012 String sql) throws SQLException {
2013 throw JDBCUtil.notSupported();
2014 }
2015
2016 /**
2017 * This method should always throw if called for a PreparedStatement or
2018 * CallableStatement.
2019 *
2020 * @param sql ignored
2021 * @throws SQLException always
2022 * @return nothing
2023 */
2024 public boolean execute(String sql) throws SQLException {
2025 throw JDBCUtil.notSupported();
2026 }
2027
2028 /**
2029 * This method should always throw if called for a PreparedStatement or
2030 * CallableStatement.
2031 *
2032 * @param sql ignored
2033 * @throws SQLException always
2034 * @return nothing
2035 */
2036 public int executeUpdate(String sql) throws SQLException {
2037 throw JDBCUtil.notSupported();
2038 }
2039
2040 /**
2041 * Does the specialized work required to free this object's resources and
2042 * that of it's parent class. <p>
2043 *
2044 * @throws SQLException if a database access error occurs
2045 */
2046 public synchronized void close() throws SQLException {
2047
2048 if (isClosed()) {
2049 return;
2050 }
2051 closeResultData();
2052
2053 HsqlException he = null;
2054
2055 try {
2056
2057 // fredt - if this is called by Connection.close() then there's no
2058 // need to free the prepared statements on the server - it is done
2059 // by Connection.close()
2060 if (!connection.isClosed) {
2061 session.execute(Result.newFreeStmtRequest(statementID));
2062 }
2063 } catch (HsqlException e) {
2064 he = e;
2065 }
2066 parameterValues = null;
2067 parameterSet = null;
2068 parameterTypes = null;
2069 parameterModes = null;
2070 resultMetaData = null;
2071 parameterMetaData = null;
2072 resultSetMetaData = null;
2073 pmd = null;
2074 connection = null;
2075 session = null;
2076 resultIn = null;
2077 resultOut = null;
2078 isClosed = true;
2079
2080 if (he != null) {
2081 throw JDBCUtil.sqlException(he);
2082 }
2083 }
2084
2085 /**
2086 * Retrieves a String representation of this object. <p>
2087 *
2088 * The representation is of the form: <p>
2089 *
2090 * class-name@hash[sql=[char-sequence], parameters=[p1, ...pi, ...pn]] <p>
2091 *
2092 * p1, ...pi, ...pn are the String representations of the currently set
2093 * parameter values that will be used with the non-batch execution
2094 * methods. <p>
2095 *
2096 * @return a String representation of this object
2097 */
2098 public String toString() {
2099
2100 StringBuffer sb = new StringBuffer();
2101 String sql;
2102 Object[] pv;
2103
2104 sb.append(super.toString());
2105
2106 sql = this.sql;
2107 pv = parameterValues;
2108
2109 if (sql == null || pv == null) {
2110 sb.append("[closed]");
2111
2112 return sb.toString();
2113 }
2114 sb.append("[sql=[").append(sql).append("]");
2115
2116 if (pv.length > 0) {
2117 sb.append(", parameters=[");
2118
2119 for (int i = 0; i < pv.length; i++) {
2120 sb.append('[');
2121 sb.append(pv[i]);
2122 sb.append("], ");
2123 }
2124 sb.setLength(sb.length() - 2);
2125 sb.append(']');
2126 }
2127 sb.append(']');
2128
2129 return sb.toString();
2130 }
2131
2132 //------------------------- JDBC 3.0 -----------------------------------
2133
2134 /**
2135 * <!-- start generic documentation -->
2136 * Sets the designated parameter to the given <code>java.net.URL</code> value.
2137 * The driver converts this to an SQL <code>DATALINK</code> value
2138 * when it sends it to the database.
2139 * <!-- end generic documentation -->
2140 *
2141 * <!-- start release-specific documentation -->
2142 * <div class="ReleaseSpecificDocumentation">
2143 * <h3>HSQLDB-Specific Information:</h3> <p>
2144 *
2145 * Including 2.0, HSQLDB does not support the DATALINK SQL type for which this
2146 * method is intended. Calling this method throws an exception.
2147 *
2148 * </div>
2149 * <!-- end release-specific documentation -->
2150 * @param parameterIndex the first parameter is 1, the second is 2, ...
2151 * @param x the <code>java.net.URL</code> object to be set
2152 * @exception SQLException if a database access error occurs or
2153 * this method is called on a closed <code>PreparedStatement</code>
2154 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2155 * @since JDK 1.4, HSQL 1.7.0
2156 */
2157 public void setURL(int parameterIndex,
2158 java.net.URL x) throws SQLException {
2159 throw JDBCUtil.notSupported();
2160 }
2161
2162 /**
2163 * <!-- start generic documentation -->
2164 * Retrieves the number, types and properties of this
2165 * <code>PreparedStatement</code> object's parameters.
2166 * <!-- end generic documentation -->
2167 *
2168 * <!-- start release-specific documentation -->
2169 * <div class="ReleaseSpecificDocumentation">
2170 * <h3>HSQLDB-Specific Information:</h3> <p>
2171 *
2172 * Since 1.7.2, this feature is supported.
2173 * </div>
2174 * <!-- end release-specific documentation -->
2175 *
2176 * @return a <code>ParameterMetaData</code> object that contains information
2177 * about the number, types and properties for each
2178 * parameter marker of this <code>PreparedStatement</code> object
2179 * @exception SQLException if a database access error occurs or
2180 * this method is called on a closed <code>PreparedStatement</code>
2181 * @see java.sql.ParameterMetaData
2182 * @since JDK 1.4, HSQL 1.7.0
2183 */
2184 public synchronized ParameterMetaData getParameterMetaData() throws SQLException {
2185
2186 checkClosed();
2187
2188 if (pmd == null) {
2189 pmd = new JDBCParameterMetaData(connection, parameterMetaData);
2190 }
2191
2192 // NOTE: pmd is declared as Object to avoid yet another #ifdef.
2193 return (ParameterMetaData) pmd;
2194 }
2195
2196 /**
2197 * Statement methods that must be overridden in this class and throw
2198 * an exception.
2199 */
2200 public int executeUpdate(String sql,
2201 int autoGeneratedKeys) throws SQLException {
2202 throw JDBCUtil.notSupported();
2203 }
2204
2205 public boolean execute(String sql,
2206 int autoGeneratedKeys) throws SQLException {
2207 throw JDBCUtil.notSupported();
2208 }
2209
2210 public int executeUpdate(String sql,
2211 int[] columnIndexes) throws SQLException {
2212 throw JDBCUtil.notSupported();
2213 }
2214
2215 public boolean execute(String sql,
2216 int[] columnIndexes) throws SQLException {
2217 throw JDBCUtil.notSupported();
2218 }
2219
2220 public int executeUpdate(String sql,
2221 String[] columnNames) throws SQLException {
2222 throw JDBCUtil.notSupported();
2223 }
2224
2225 public boolean execute(String sql,
2226 String[] columnNames) throws SQLException {
2227 throw JDBCUtil.notSupported();
2228 }
2229
2230 /**
2231 * <!-- start generic documentation -->
2232 * Moves to this <code>Statement</code> object's next result, deals with
2233 * any current <code>ResultSet</code> object(s) according to the instructions
2234 * specified by the given flag, and returns
2235 * <code>true</code> if the next result is a <code>ResultSet</code> object.
2236 *
2237 * <P>There are no more results when the following is true:
2238 * <PRE>
2239 * // stmt is a Statement object
2240 * ((stmt.getMoreResults(current) == false) && (stmt.getUpdateCount() == -1))
2241 * </PRE>
2242 * <!-- end generic documentation -->
2243 *
2244 * <!-- start release-specific documentation -->
2245 * <div class="ReleaseSpecificDocumentation">
2246 * <h3>HSQLDB-Specific Information:</h3> <p>
2247 *
2248 * HSQLDB supports this feature. <p>
2249 *
2250 * This is used with CallableStatement objects that return multiple
2251 * ResultSet objects.
2252 * </div>
2253 * <!-- end release-specific documentation -->
2254 *
2255 * @param current one of the following <code>Statement</code>
2256 * constants indicating what should happen to current
2257 * <code>ResultSet</code> objects obtained using the method
2258 * <code>getResultSet</code>:
2259 * <code>Statement.CLOSE_CURRENT_RESULT</code>,
2260 * <code>Statement.KEEP_CURRENT_RESULT</code>, or
2261 * <code>Statement.CLOSE_ALL_RESULTS</code>
2262 * @return <code>true</code> if the next result is a <code>ResultSet</code>
2263 * object; <code>false</code> if it is an update count or there are no
2264 * more results
2265 * @exception SQLException if a database access error occurs,
2266 * this method is called on a closed <code>Statement</code> or the argument
2267 * supplied is not one of the following:
2268 * <code>Statement.CLOSE_CURRENT_RESULT</code>,
2269 * <code>Statement.KEEP_CURRENT_RESULT</code>, or
2270 * <code>Statement.CLOSE_ALL_RESULTS</code>
2271 * @since JDK 1.4, HSQLDB 1.7
2272 * @see #execute
2273 */
2274 public synchronized boolean getMoreResults(
2275 int current) throws SQLException {
2276 return super.getMoreResults(current);
2277 }
2278
2279 /**
2280 * <!-- start generic documentation -->
2281 * Retrieves any auto-generated keys created as a result of executing this
2282 * <code>Statement</code> object. If this <code>Statement</code> object did
2283 * not generate any keys, an empty <code>ResultSet</code>
2284 * object is returned.
2285 * <p>(JDBC4 clarification:)
2286 * <p><B>Note:</B>If the columns which represent the auto-generated keys were not specified,
2287 * the JDBC driver implementation will determine the columns which best represent the auto-generated keys.
2288 * <!-- end generic documentation -->
2289 *
2290 * <!-- start release-specific documentation -->
2291 * <div class="ReleaseSpecificDocumentation">
2292 * <h3>HSQLDB-Specific Information:</h3> <p>
2293 *
2294 * Starting with version 2.0, HSQLDB supports this feature with single-row and
2295 * multi-row insert, update and merge statements. <p>
2296 *
2297 * This method returns a result set only if
2298 * the executeUpdate methods that was used is one of the three methods that
2299 * have the extra parameter indicating return of generated keys<p>
2300 *
2301 * If the executeUpdate method did not specify the columns which represent
2302 * the auto-generated keys the IDENTITY column or GENERATED column(s) of the
2303 * table are returned.<p>
2304 *
2305 * The executeUpdate methods with column indexes or column names return the
2306 * post-insert or post-update values of the specified columns, whether the
2307 * columns are generated or not. This allows values that have been modified
2308 * by execution of triggers to be returned.<p>
2309 *
2310 * If column names or indexes provided by the user in the executeUpdate()
2311 * method calls do not correspond to table columns (incorrect names or
2312 * indexes larger than the column count), an empty result is returned.
2313 *
2314 * </div>
2315 * <!-- end release-specific documentation -->
2316 *
2317 * @return a <code>ResultSet</code> object containing the auto-generated key(s)
2318 * generated by the execution of this <code>Statement</code> object
2319 * @exception SQLException if a database access error occurs or
2320 * this method is called on a closed <code>Statement</code>
2321 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2322 * @since JDK 1.4, HSQLDB 1.7
2323 */
2324 public synchronized ResultSet getGeneratedKeys() throws SQLException {
2325 return getGeneratedResultSet();
2326 }
2327
2328 /**
2329 * <!-- start generic documentation -->
2330 * Retrieves the result set holdability for <code>ResultSet</code> objects
2331 * generated by this <code>Statement</code> object.
2332 * <!-- end generic documentation -->
2333 *
2334 * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2335 * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2336 * @exception SQLException if a database access error occurs or
2337 * this method is called on a closed <code>Statement</code>
2338 * @since JDK 1.4, HSQLDB 1.7
2339 */
2340 public synchronized int getResultSetHoldability() throws SQLException {
2341
2342 if (isClosed || connection.isClosed) {
2343 checkClosed();
2344 }
2345
2346 return ResultProperties.getJDBCHoldability(rsProperties);
2347 }
2348
2349 //------------------------- JDBC 4.0 -----------------------------------
2350
2351 /**
2352 * Retrieves whether this <code>Statement</code> object has been closed. A <code>Statement</code> is closed if the
2353 * method close has been called on it, or if it is automatically closed.
2354 * @return true if this <code>Statement</code> object is closed; false if it is still open
2355 * @throws SQLException if a database access error occurs
2356 * @since JDK 1.6, HSQLDB 2.0
2357 */
2358 public synchronized boolean isClosed() {
2359 return isClosed;
2360 }
2361
2362 /**
2363 * Sets the designated parameter to the given <code>java.sql.RowId</code> object. The
2364 * driver converts this to a SQL <code>ROWID</code> value when it sends it
2365 * to the database
2366 *
2367 * @param parameterIndex the first parameter is 1, the second is 2, ...
2368 * @param x the parameter value
2369 * @throws SQLException if a database access error occurs or
2370 * this method is called on a closed <code>PreparedStatement</code>
2371 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2372 *
2373 * @since JDK 1.6, HSQLDB 2.0
2374 */
2375
2376 //#ifdef JAVA6
2377 public void setRowId(int parameterIndex, RowId x) throws SQLException {
2378 throw JDBCUtil.notSupported();
2379 }
2380
2381 //#endif JAVA6
2382
2383 /**
2384 * Sets the designated parameter to the given <code>String</code> object.
2385 * The driver converts this to a SQL <code>NCHAR</code> or
2386 * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
2387 * (depending on the argument's
2388 * size relative to the driver's limits on <code>NVARCHAR</code> values)
2389 * when it sends it to the database.
2390 *
2391 * @param parameterIndex of the first parameter is 1, the second is 2, ...
2392 * @param value the parameter value
2393 * @throws SQLException if the driver does not support national
2394 * character sets; if the driver can detect that a data conversion
2395 * error could occur ; if a database access error occurs; or
2396 * this method is called on a closed <code>PreparedStatement</code>
2397 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2398 * @since JDK 1.6, HSQLDB 2.0
2399 */
2400 public synchronized void setNString(int parameterIndex,
2401 String value) throws SQLException {
2402 setString(parameterIndex, value);
2403 }
2404
2405 /**
2406 * Sets the designated parameter to a <code>Reader</code> object. The
2407 * <code>Reader</code> reads the data till end-of-file is reached. The
2408 * driver does the necessary conversion from Java character format to
2409 * the national character set in the database.
2410 * @param parameterIndex of the first parameter is 1, the second is 2, ...
2411 * @param value the parameter value
2412 * @param length the number of characters in the parameter data.
2413 * @throws SQLException if the driver does not support national
2414 * character sets; if the driver can detect that a data conversion
2415 * error could occur ; if a database access error occurs; or
2416 * this method is called on a closed <code>PreparedStatement</code>
2417 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2418 * @since JDK 1.6, HSQLDB 2.0
2419 */
2420 public synchronized void setNCharacterStream(int parameterIndex,
2421 Reader value, long length) throws SQLException {
2422 setCharacterStream(parameterIndex, value, length);
2423 }
2424
2425 /**
2426 * Sets the designated parameter to a <code>java.sql.NClob</code> object. The driver converts this to a
2427 * SQL <code>NCLOB</code> value when it sends it to the database.
2428 * @param parameterIndex of the first parameter is 1, the second is 2, ...
2429 * @param value the parameter value
2430 * @throws SQLException if the driver does not support national
2431 * character sets; if the driver can detect that a data conversion
2432 * error could occur ; if a database access error occurs; or
2433 * this method is called on a closed <code>PreparedStatement</code>
2434 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2435 * @since JDK 1.6, HSQLDB 2.0
2436 */
2437
2438 //#ifdef JAVA6
2439 public synchronized void setNClob(int parameterIndex,
2440 NClob value) throws SQLException {
2441 setClob(parameterIndex, value);
2442 }
2443
2444 //#endif JAVA6
2445
2446 /** @todo 1.9.0 - implement streaming and remove length limits */
2447
2448 /**
2449 * Sets the designated parameter to a <code>Reader</code> object. The reader must contain the number
2450 * of characters specified by length otherwise a <code>SQLException</code> will be
2451 * generated when the <code>PreparedStatement</code> is executed.
2452 * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
2453 * because it informs the driver that the parameter value should be sent to
2454 * the server as a <code>CLOB</code>. When the <code>setCharacterStream</code> method is used, the
2455 * driver may have to do extra work to determine whether the parameter
2456 * data should be send to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
2457 * @param parameterIndex index of the first parameter is 1, the second is 2, ...
2458 * @param reader An object that contains the data to set the parameter value to.
2459 * @param length the number of characters in the parameter data.
2460 * @throws SQLException if a database access error occurs, this method is called on
2461 * a closed <code>PreparedStatement</code>, if parameterIndex does not correspond to a parameter
2462 * marker in the SQL statement, or if the length specified is less than zero.
2463 *
2464 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2465 * @since JDK 1.6, HSQLDB 2.0
2466 */
2467 public synchronized void setClob(int parameterIndex, Reader reader,
2468 long length) throws SQLException {
2469 setCharacterStream(parameterIndex, reader, length);
2470 }
2471
2472 /** @todo 1.9.0 - implement streaming and remove length limits */
2473
2474 /**
2475 * Sets the designated parameter to a <code>InputStream</code> object. The input stream must contain the number
2476 * of characters specified by length otherwise a <code>SQLException</code> will be
2477 * generated when the <code>PreparedStatement</code> is executed.
2478 * This method differs from the <code>setBinaryStream (int, InputStream, int)</code>
2479 * method because it informs the driver that the parameter value should be
2480 * sent to the server as a <code>BLOB</code>. When the <code>setBinaryStream</code> method is used,
2481 * the driver may have to do extra work to determine whether the parameter
2482 * data should be send to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
2483 * <!-- start release-specific documentation -->
2484 * <div class="ReleaseSpecificDocumentation">
2485 * <h3>HSQLDB-Specific Information:</h3> <p>
2486 *
2487 * In HSQLDB 2.0, this method uses streaming to send the data when the
2488 * stream is assigned to a BLOB target. For other binary targets the
2489 * stream is read on the client side and a byte array is sent.
2490 * </div>
2491 * <!-- end release-specific documentation -->
2492 *
2493 * @param parameterIndex index of the first parameter is 1,
2494 * the second is 2, ...
2495 * @param inputStream An object that contains the data to set the parameter
2496 * value to.
2497 * @param length the number of bytes in the parameter data.
2498 * @throws SQLException if a database access error occurs,
2499 * this method is called on a closed <code>PreparedStatement</code>,
2500 * if parameterIndex does not correspond
2501 * to a parameter marker in the SQL statement, if the length specified
2502 * is less than zero or if the number of bytes in the input stream does not match
2503 * the specified length.
2504 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2505 *
2506 * @since JDK 1.6, HSQLDB 2.0
2507 */
2508 public synchronized void setBlob(int parameterIndex,
2509 InputStream inputStream,
2510 long length) throws SQLException {
2511 setBinaryStream(parameterIndex, inputStream, length);
2512 }
2513
2514 /**
2515 * Sets the designated parameter to a <code>Reader</code> object. The reader must contain the number
2516 * of characters specified by length otherwise a <code>SQLException</code> will be
2517 * generated when the <code>PreparedStatement</code> is executed.
2518 * This method differs from the <code>setCharacterStream (int, Reader, int)</code> method
2519 * because it informs the driver that the parameter value should be sent to
2520 * the server as a <code>NCLOB</code>. When the <code>setCharacterStream</code> method is used, the
2521 * driver may have to do extra work to determine whether the parameter
2522 * data should be send to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
2523 * @param parameterIndex index of the first parameter is 1, the second is 2, ...
2524 * @param reader An object that contains the data to set the parameter value to.
2525 * @param length the number of characters in the parameter data.
2526 * @throws SQLException if parameterIndex does not correspond to a parameter
2527 * marker in the SQL statement; if the length specified is less than zero;
2528 * if the driver does not support national character sets;
2529 * if the driver can detect that a data conversion
2530 * error could occur; if a database access error occurs or
2531 * this method is called on a closed <code>PreparedStatement</code>
2532 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2533 *
2534 * @since JDK 1.6, HSQLDB 2.0
2535 */
2536 public synchronized void setNClob(int parameterIndex, Reader reader,
2537 long length) throws SQLException {
2538 setClob(parameterIndex, reader, length);
2539 }
2540
2541 /**
2542 * Sets the designated parameter to the given <code>java.sql.SQLXML</code> object.
2543 * The driver converts this to an
2544 * SQL <code>XML</code> value when it sends it to the database.
2545 * <p>
2546 *
2547 * @param parameterIndex index of the first parameter is 1, the second is 2, ...
2548 * @param xmlObject a <code>SQLXML</code> object that maps an SQL <code>XML</code> value
2549 * @throws SQLException if a database access error occurs,
2550 * this method is called on a closed <code>PreparedStatement</code>
2551 * or the <code>java.xml.transform.Result</code>,
2552 * <code>Writer</code> or <code>OutputStream</code> has not been closed for
2553 * the <code>SQLXML</code> object
2554 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2555 *
2556 * @since JDK 1.6, HSQLDB 2.0
2557 */
2558
2559 //#ifdef JAVA6
2560 public void setSQLXML(int parameterIndex,
2561 SQLXML xmlObject) throws SQLException {
2562 throw JDBCUtil.notSupported();
2563 }
2564
2565 //#endif JAVA6
2566 // --------------------------- Added: Mustang Build 86 -------------------------
2567
2568 /** @todo 1.9.0 - implement streaming and remove length limits */
2569
2570 /**
2571 * Sets the designated parameter to the given input stream, which will have
2572 * the specified number of bytes.
2573 * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
2574 * parameter, it may be more practical to send it via a
2575 * <code>java.io.InputStream</code>. Data will be read from the stream
2576 * as needed until end-of-file is reached. The JDBC driver will
2577 * do any necessary conversion from ASCII to the database char format.
2578 *
2579 * <P><B>Note:</B> This stream object can either be a standard
2580 * Java stream object or your own subclass that implements the
2581 * standard interface.
2582 *
2583 * <!-- start release-specific documentation -->
2584 * <div class="ReleaseSpecificDocumentation">
2585 * <h3>HSQLDB-Specific Information:</h3> <p>
2586 *
2587 * From HSQLDB 2.0 this method uses the US-ASCII character encoding to convert bytes
2588 * from the stream into the characters of a String.<p>
2589 * This method does not use streaming to send the data,
2590 * whether the target is a CLOB or other binary object.<p>
2591 *
2592 * For long streams (larger than a few megabytes) with CLOB targets,
2593 * it is more efficient to use a version of setCharacterStream which takes
2594 * the a length parameter.
2595 * </div>
2596 * <!-- end release-specific documentation -->
2597 * @param parameterIndex the first parameter is 1, the second is 2, ...
2598 * @param x the Java input stream that contains the ASCII parameter value
2599 * @param length the number of bytes in the stream
2600 * @exception SQLException if a database access error occurs or
2601 * this method is called on a closed <code>PreparedStatement</code>
2602 * @since JDK 1.6 b86, HSQLDB 2.0
2603 */
2604 public synchronized void setAsciiStream(int parameterIndex,
2605 java.io.InputStream x, long length) throws SQLException {
2606
2607 if (length < 0) {
2608 throw JDBCUtil.sqlException(ErrorCode.JDBC_INVALID_ARGUMENT,
2609 "length: " + length);
2610 }
2611 setAscStream(parameterIndex, x, (long) length);
2612 }
2613
2614 void setAscStream(int parameterIndex, java.io.InputStream x,
2615 long length) throws SQLException {
2616
2617 if (length > Integer.MAX_VALUE) {
2618 throw JDBCUtil.sqlException(ErrorCode.X_22001);
2619 }
2620
2621 if (x == null) {
2622 throw JDBCUtil.nullArgument("x");
2623 }
2624
2625 try {
2626 String s = StringConverter.inputStreamToString(x, "US-ASCII");
2627
2628 if (length >= 0 && s.length() > length) {
2629 s = s.substring(0, (int) length);
2630 }
2631 setParameter(parameterIndex, s);
2632 } catch (IOException e) {
2633 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR, null, e);
2634 }
2635 }
2636
2637 /**
2638 * Sets the designated parameter to the given input stream, which will have
2639 * the specified number of bytes.
2640 * When a very large binary value is input to a <code>LONGVARBINARY</code>
2641 * parameter, it may be more practical to send it via a
2642 * <code>java.io.InputStream</code> object. The data will be read from the
2643 * stream as needed until end-of-file is reached.
2644 *
2645 * <P><B>Note:</B> This stream object can either be a standard
2646 * Java stream object or your own subclass that implements the
2647 * standard interface.
2648 *
2649 * <!-- start release-specific documentation -->
2650 * <div class="ReleaseSpecificDocumentation">
2651 * <h3>HSQLDB-Specific Information:</h3> <p>
2652 *
2653 * This method uses streaming to send the data when the
2654 * stream is assigned to a BLOB target. For other binary targets the
2655 * stream is read on the client side and a byte array is sent.
2656 * </div>
2657 * <!-- end release-specific documentation -->
2658 *
2659 * @param parameterIndex the first parameter is 1, the second is 2, ...
2660 * @param x the java input stream which contains the binary parameter value
2661 * @param length the number of bytes in the stream
2662 * @exception SQLException if a database access error occurs or
2663 * this method is called on a closed <code>PreparedStatement</code>
2664 * @since JDK 1.6 b86, HSQLDB 2.0
2665 */
2666 public synchronized void setBinaryStream(int parameterIndex,
2667 java.io.InputStream x, long length) throws SQLException {
2668
2669 if (length < 0) {
2670 throw JDBCUtil.sqlException(ErrorCode.JDBC_INVALID_ARGUMENT,
2671 "length: " + length);
2672 }
2673 setBinStream(parameterIndex, x, length);
2674 }
2675
2676 private void setBinStream(int parameterIndex, java.io.InputStream x,
2677 long length) throws SQLException {
2678
2679 if (isClosed || connection.isClosed) {
2680 checkClosed();
2681 }
2682
2683 if (parameterTypes[parameterIndex - 1].typeCode == Types.SQL_BLOB) {
2684 setBlobParameter(parameterIndex, x, length);
2685
2686 return;
2687 }
2688
2689 if (length > Integer.MAX_VALUE) {
2690 String msg = "Maximum Blob input length exceeded: " + length;
2691
2692 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR, msg);
2693 }
2694
2695 try {
2696 HsqlByteArrayOutputStream output;
2697
2698 if (length < 0) {
2699 output = new HsqlByteArrayOutputStream(x);
2700 } else {
2701 output = new HsqlByteArrayOutputStream(x, (int) length);
2702 }
2703 setParameter(parameterIndex, output.toByteArray());
2704 } catch (Throwable e) {
2705 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR,
2706 e.toString(), e);
2707 }
2708 }
2709
2710 /**
2711 * Sets the designated parameter to the given <code>Reader</code>
2712 * object, which is the given number of characters long.
2713 * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
2714 * parameter, it may be more practical to send it via a
2715 * <code>java.io.Reader</code> object. The data will be read from the stream
2716 * as needed until end-of-file is reached. The JDBC driver will
2717 * do any necessary conversion from UNICODE to the database char format.
2718 *
2719 * <P><B>Note:</B> This stream object can either be a standard
2720 * Java stream object or your own subclass that implements the
2721 * standard interface.
2722 *
2723 * <!-- start release-specific documentation -->
2724 * <div class="ReleaseSpecificDocumentation">
2725 * <h3>HSQLDB-Specific Information:</h3> <p>
2726 *
2727 * This method uses streaming to send data
2728 * when the target is a CLOB.<p>
2729 * </div>
2730 * <!-- end release-specific documentation -->
2731 * @param parameterIndex the first parameter is 1, the second is 2, ...
2732 * @param reader the <code>java.io.Reader</code> object that contains the
2733 * Unicode data
2734 * @param length the number of characters in the stream
2735 * @exception SQLException if a database access error occurs or
2736 * this method is called on a closed <code>PreparedStatement</code>
2737 * @since JDK 1.6 b86, HSQLDB 2.0
2738 */
2739 public synchronized void setCharacterStream(int parameterIndex,
2740 java.io.Reader reader, long length) throws SQLException {
2741
2742 if (length < 0) {
2743 throw JDBCUtil.sqlException(ErrorCode.JDBC_INVALID_ARGUMENT,
2744 "length: " + length);
2745 }
2746 setCharStream(parameterIndex, reader, length);
2747 }
2748
2749 private void setCharStream(int parameterIndex, java.io.Reader reader,
2750 long length) throws SQLException {
2751
2752 checkSetParameterIndex(parameterIndex);
2753
2754 if (parameterTypes[parameterIndex - 1].typeCode == Types.SQL_CLOB) {
2755 setClobParameter(parameterIndex, reader, length);
2756
2757 return;
2758 }
2759
2760 if (length > Integer.MAX_VALUE) {
2761 String msg = "Maximum Clob input length exceeded: " + length;
2762
2763 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR, msg);
2764 }
2765
2766 try {
2767 CharArrayWriter writer;
2768
2769 if (length < 0) {
2770 writer = new CharArrayWriter(reader);
2771 } else {
2772 writer = new CharArrayWriter(reader, (int) length);
2773 }
2774 setParameter(parameterIndex, writer.toString());
2775 } catch (Throwable e) {
2776 throw JDBCUtil.sqlException(ErrorCode.JDBC_INPUTSTREAM_ERROR,
2777 e.toString(), e);
2778 }
2779 }
2780
2781 /**
2782 * Sets the designated parameter to the given input stream.
2783 * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
2784 * parameter, it may be more practical to send it via a
2785 * <code>java.io.InputStream</code>. Data will be read from the stream
2786 * as needed until end-of-file is reached. The JDBC driver will
2787 * do any necessary conversion from ASCII to the database char format.
2788 *
2789 * <P><B>Note:</B> This stream object can either be a standard
2790 * Java stream object or your own subclass that implements the
2791 * standard interface.
2792 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2793 * it might be more efficient to use a version of
2794 * <code>setAsciiStream</code> which takes a length parameter.
2795 *
2796 * <!-- start release-specific documentation -->
2797 * <div class="ReleaseSpecificDocumentation">
2798 * <h3>HSQLDB-Specific Information:</h3> <p>
2799 *
2800 * In HSQLDB 2.0, this method does not use streaming to send the data,
2801 * whether the target is a CLOB or other binary object.
2802 *
2803 * For long streams (larger than a few megabytes), it is more efficient to
2804 * use a version of setCharacterStream which takes the a length parameter.
2805 * </div>
2806 * <!-- end release-specific documentation -->
2807 *
2808 * @param parameterIndex the first parameter is 1, the second is 2, ...
2809 * @param x the Java input stream that contains the ASCII parameter value
2810 * @exception SQLException if parameterIndex does not correspond to a parameter
2811 * marker in the SQL statement; if a database access error occurs or
2812 * this method is called on a closed <code>PreparedStatement</code>
2813 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2814 * @since 1.6
2815 */
2816 public void setAsciiStream(int parameterIndex,
2817 java.io.InputStream x) throws SQLException {
2818 setAscStream(parameterIndex, x, -1);
2819 }
2820
2821 /** @todo 1.9.0 - implement streaming and remove length limits */
2822
2823 /**
2824 * Sets the designated parameter to the given input stream.
2825 * When a very large binary value is input to a <code>LONGVARBINARY</code>
2826 * parameter, it may be more practical to send it via a
2827 * <code>java.io.InputStream</code> object. The data will be read from the
2828 * stream as needed until end-of-file is reached.
2829 *
2830 * <P><B>Note:</B> This stream object can either be a standard
2831 * Java stream object or your own subclass that implements the
2832 * standard interface.
2833 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2834 * it might be more efficient to use a version of
2835 * <code>setBinaryStream</code> which takes a length parameter.
2836 *
2837 * <!-- start release-specific documentation -->
2838 * <div class="ReleaseSpecificDocumentation">
2839 * <!-- start release-specific documentation -->
2840 * <div class="ReleaseSpecificDocumentation">
2841 * <h3>HSQLDB-Specific Information:</h3> <p>
2842 *
2843 * This method does not use streaming to send the data,
2844 * whether the target is a CLOB or other binary object.<p>
2845 *
2846 * For long streams (larger than a few megabytes) with CLOB targets,
2847 * it is more efficient to use a version of setCharacterStream which takes
2848 * the a length parameter.
2849 * </div>
2850 * <!-- end release-specific documentation -->
2851 *
2852 * @param parameterIndex the first parameter is 1, the second is 2, ...
2853 * @param x the java input stream which contains the binary parameter value
2854 * @exception SQLException if parameterIndex does not correspond to a parameter
2855 * marker in the SQL statement; if a database access error occurs or
2856 * this method is called on a closed <code>PreparedStatement</code>
2857 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2858 * @since 1.6
2859 */
2860 public synchronized void setBinaryStream(int parameterIndex,
2861 java.io.InputStream x) throws SQLException {
2862 setBinStream(parameterIndex, x, -1);
2863 }
2864
2865 /** @todo 1.9.0 - implement streaming and remove length limits */
2866
2867 /**
2868 * Sets the designated parameter to the given <code>Reader</code>
2869 * object.
2870 * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
2871 * parameter, it may be more practical to send it via a
2872 * <code>java.io.Reader</code> object. The data will be read from the stream
2873 * as needed until end-of-file is reached. The JDBC driver will
2874 * do any necessary conversion from UNICODE to the database char format.
2875 *
2876 * <P><B>Note:</B> This stream object can either be a standard
2877 * Java stream object or your own subclass that implements the
2878 * standard interface.
2879 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2880 * it might be more efficient to use a version of
2881 * <code>setCharacterStream</code> which takes a length parameter.
2882 *
2883 * <!-- start release-specific documentation -->
2884 * <div class="ReleaseSpecificDocumentation">
2885 * <h3>HSQLDB-Specific Information:</h3> <p>
2886 *
2887 * In HSQLDB 2.0, this method does not use streaming to send the data,
2888 * whether the target is a CLOB or other binary object.
2889 *
2890 * For long streams (larger than a few megabytes), it is more efficient to
2891 * use a version of setCharacterStream which takes the a length parameter.
2892 * </div>
2893 * <!-- end release-specific documentation -->
2894 *
2895 * @param parameterIndex the first parameter is 1, the second is 2, ...
2896 * @param reader the <code>java.io.Reader</code> object that contains the
2897 * Unicode data
2898 * @exception SQLException if parameterIndex does not correspond to a parameter
2899 * marker in the SQL statement; if a database access error occurs or
2900 * this method is called on a closed <code>PreparedStatement</code>
2901 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2902 * @since 1.6
2903 */
2904 public void setCharacterStream(int parameterIndex,
2905 java.io.Reader reader) throws SQLException {
2906 setCharStream(parameterIndex, reader, -1);
2907 }
2908
2909 /** @todo 1.9.0 - implement streaming and remove length limits */
2910
2911 /**
2912 * Sets the designated parameter to a <code>Reader</code> object. The
2913 * <code>Reader</code> reads the data till end-of-file is reached. The
2914 * driver does the necessary conversion from Java character format to
2915 * the national character set in the database.
2916 *
2917 * <P><B>Note:</B> This stream object can either be a standard
2918 * Java stream object or your own subclass that implements the
2919 * standard interface.
2920 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2921 * it might be more efficient to use a version of
2922 * <code>setNCharacterStream</code> which takes a length parameter.
2923 *
2924 * @param parameterIndex of the first parameter is 1, the second is 2, ...
2925 * @param value the parameter value
2926 * @throws SQLException if parameterIndex does not correspond to a parameter
2927 * marker in the SQL statement; if the driver does not support national
2928 * character sets; if the driver can detect that a data conversion
2929 * error could occur; if a database access error occurs; or
2930 * this method is called on a closed <code>PreparedStatement</code>
2931 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2932 * @since 1.6
2933 */
2934 public void setNCharacterStream(int parameterIndex,
2935 Reader value) throws SQLException {
2936 setCharStream(parameterIndex, value, -1);
2937 }
2938
2939 /** @todo 1.9.0 - implement streaming and remove length limits */
2940
2941 /**
2942 * Sets the designated parameter to a <code>Reader</code> object.
2943 * This method differs from the <code>setCharacterStream (int, Reader)</code> method
2944 * because it informs the driver that the parameter value should be sent to
2945 * the server as a <code>CLOB</code>. When the <code>setCharacterStream</code> method is used, the
2946 * driver may have to do extra work to determine whether the parameter
2947 * data should be sent to the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>
2948 *
2949 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2950 * it might be more efficient to use a version of
2951 * <code>setClob</code> which takes a length parameter.
2952 *
2953 * @param parameterIndex index of the first parameter is 1, the second is 2, ...
2954 * @param reader An object that contains the data to set the parameter value to.
2955 * @throws SQLException if parameterIndex does not correspond to a parameter
2956 * marker in the SQL statement; if a database access error occurs; this method is called on
2957 * a closed <code>PreparedStatement</code>or if parameterIndex does not correspond to a parameter
2958 * marker in the SQL statement
2959 *
2960 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2961 * @since 1.6
2962 */
2963 public void setClob(int parameterIndex,
2964 Reader reader) throws SQLException {
2965 setCharStream(parameterIndex, reader, -1);
2966 }
2967
2968 /** @todo 1.9.0 - implement streaming and remove length limits */
2969
2970 /**
2971 * Sets the designated parameter to a <code>InputStream</code> object.
2972 * This method differs from the <code>setBinaryStream (int, InputStream)</code>
2973 * method because it informs the driver that the parameter value should be
2974 * sent to the server as a <code>BLOB</code>. When the <code>setBinaryStream</code> method is used,
2975 * the driver may have to do extra work to determine whether the parameter
2976 * data should be sent to the server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
2977 *
2978 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
2979 * it might be more efficient to use a version of
2980 * <code>setBlob</code> which takes a length parameter.
2981 *
2982 * @param parameterIndex index of the first parameter is 1,
2983 * the second is 2, ...
2984 * @param inputStream An object that contains the data to set the parameter
2985 * value to.
2986 * @throws SQLException if parameterIndex does not correspond to a parameter
2987 * marker in the SQL statement; if a database access error occurs;
2988 * this method is called on a closed <code>PreparedStatement</code> or
2989 * if parameterIndex does not correspond
2990 * to a parameter marker in the SQL statement,
2991 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
2992 *
2993 * @since 1.6
2994 */
2995 public void setBlob(int parameterIndex,
2996 InputStream inputStream) throws SQLException {
2997 setBinStream(parameterIndex, inputStream, -1);
2998 }
2999
3000 /** @todo 1.9.0 - implement streaming and remove length limits */
3001
3002 /**
3003 * Sets the designated parameter to a <code>Reader</code> object.
3004 * This method differs from the <code>setCharacterStream (int, Reader)</code> method
3005 * because it informs the driver that the parameter value should be sent to
3006 * the server as a <code>NCLOB</code>. When the <code>setCharacterStream</code> method is used, the
3007 * driver may have to do extra work to determine whether the parameter
3008 * data should be sent to the server as a <code>LONGNVARCHAR</code> or a <code>NCLOB</code>
3009 * <P><B>Note:</B> Consult your JDBC driver documentation to determine if
3010 * it might be more efficient to use a version of
3011 * <code>setNClob</code> which takes a length parameter.
3012 *
3013 * @param parameterIndex index of the first parameter is 1, the second is 2, ...
3014 * @param reader An object that contains the data to set the parameter value to.
3015 * @throws SQLException if parameterIndex does not correspond to a parameter
3016 * marker in the SQL statement;
3017 * if the driver does not support national character sets;
3018 * if the driver can detect that a data conversion
3019 * error could occur; if a database access error occurs or
3020 * this method is called on a closed <code>PreparedStatement</code>
3021 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
3022 *
3023 * @since 1.6
3024 */
3025 public void setNClob(int parameterIndex,
3026 Reader reader) throws SQLException {
3027 setCharStream(parameterIndex, reader, -1);
3028 }
3029
3030 /**
3031 * <!-- start generic documentation -->
3032 * Retrieves the maximum number of bytes that can be
3033 * returned for character and binary column values in a <code>ResultSet</code>
3034 * object produced by this <code>Statement</code> object.
3035 * This limit applies only to <code>BINARY</code>, <code>VARBINARY</code>,
3036 * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
3037 * (JDBC4 new:) <code>NCHAR</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>
3038 * and <code>LONGVARCHAR</code> columns. If the limit is exceeded, the
3039 * excess data is silently discarded.
3040 * <!-- end generic documentation -->
3041 *
3042 * <!-- start release-specific documentation -->
3043 * <div class="ReleaseSpecificDocumentation">
3044 * <h3>HSQLDB-Specific Information:</h3> <p>
3045 *
3046 * HSQLDB always returns zero, meaning there is no limit.
3047 * </div>
3048 * <!-- end release-specific documentation -->
3049 *
3050 * @return the current column size limit for columns storing character and
3051 * binary values; zero means there is no limit
3052 * @exception SQLException if a database access error occurs or
3053 * this method is called on a closed <code>Statement</code>
3054 * @see #setMaxFieldSize
3055 */
3056 public synchronized int getMaxFieldSize() throws SQLException {
3057
3058 if (isClosed || connection.isClosed) {
3059 checkClosed();
3060 }
3061
3062 return 0;
3063 }
3064
3065 /**
3066 * <!-- start generic documentation -->
3067 * (JDBC4 clarification:) Sets the limit for the maximum number of bytes in a <code>ResultSet</code>
3068 * Sets the limit for the maximum number of bytes that can be returned for
3069 * character and binary column values in a <code>ResultSet</code>
3070 * object produced by this <code>Statement</code> object.
3071 *
3072 * This limit applies
3073 * only to <code>BINARY</code>, <code>VARBINARY</code>,
3074 * <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
3075 * (JDBC4 new:) <code>NCHAR</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code> and
3076 * <code>LONGVARCHAR</code> fields. If the limit is exceeded, the excess data
3077 * is silently discarded. For maximum portability, use values
3078 * greater than 256.
3079 * <!-- emd generic documentation -->
3080 *
3081 * <!-- start release-specific documentation -->
3082 * <div class="ReleaseSpecificDocumentation">
3083 * <h3>HSQLDB-Specific Information:</h3> <p>
3084 *
3085 * To present, calls to this method are simply ignored; HSQLDB always
3086 * stores the full number of bytes when dealing with any of the field types
3087 * mentioned above. These types all have an absolute maximum element upper
3088 * bound determined by the Java array index limit
3089 * java.lang.Integer.MAX_VALUE. For XXXBINARY types, this translates to
3090 * Integer.MAX_VALUE bytes. For XXXCHAR types, this translates to
3091 * 2 * Integer.MAX_VALUE bytes (2 bytes / character). <p>
3092 *
3093 * In practice, field sizes are limited to values much smaller than the
3094 * absolute maximum element upper bound, in particular due to limits imposed
3095 * on the maximum available Java heap memory.
3096 * </div>
3097 * <!-- end release-specific documentation -->
3098 *
3099 * @param max the new column size limit in bytes; zero means there is no limit
3100 * @exception SQLException if a database access error occurs,
3101 * this method is called on a closed <code>Statement</code>
3102 * or the condition max >= 0 is not satisfied
3103 * @see #getMaxFieldSize
3104 */
3105 public synchronized void setMaxFieldSize(int max) throws SQLException {
3106
3107 if (isClosed || connection.isClosed) {
3108 checkClosed();
3109 }
3110
3111 if (max < 0) {
3112 throw JDBCUtil.outOfRangeArgument();
3113 }
3114 }
3115
3116 /**
3117 * <!-- start generic documentation -->
3118 * Retrieves the maximum number of rows that a
3119 * <code>ResultSet</code> object produced by this
3120 * <code>Statement</code> object can contain. If this limit is exceeded,
3121 * the excess rows are silently dropped.
3122 * <!-- start generic documentation -->
3123 *
3124 * @return the current maximum number of rows for a <code>ResultSet</code>
3125 * object produced by this <code>Statement</code> object;
3126 * zero means there is no limit
3127 * @exception SQLException if a database access error occurs or
3128 * this method is called on a closed <code>Statement</code>
3129 * @see #setMaxRows
3130 */
3131 public synchronized int getMaxRows() throws SQLException {
3132
3133 if (isClosed || connection.isClosed) {
3134 checkClosed();
3135 }
3136
3137 return maxRows;
3138 }
3139
3140 /**
3141 * <!-- start generic documentation -->
3142 * (JDBC4 clarification:)
3143 * Sets the limit for the maximum number of rows that any
3144 * <code>ResultSet</code> object generated by this <code>Statement</code>
3145 * object can contain to the given number.
3146 * If the limit is exceeded, the excess
3147 * rows are silently dropped.
3148 * <!-- end generic documentation -->
3149 *
3150 * @param max the new max rows limit; zero means there is no limit
3151 * @exception SQLException if a database access error occurs,
3152 * this method is called on a closed <code>Statement</code>
3153 * or the condition max >= 0 is not satisfied
3154 * @see #getMaxRows
3155 */
3156 public synchronized void setMaxRows(int max) throws SQLException {
3157
3158 if (isClosed || connection.isClosed) {
3159 checkClosed();
3160 }
3161
3162 if (max < 0) {
3163 throw JDBCUtil.outOfRangeArgument();
3164 }
3165 maxRows = max;
3166 }
3167
3168 /**
3169 * <!-- start generic documentation -->
3170 * Retrieves the number of seconds the driver will
3171 * wait for a <code>Statement</code> object to execute.
3172 * If the limit is exceeded, a
3173 * <code>SQLException</code> is thrown.
3174 * <!-- end generic documentation -->
3175 *
3176 * <!-- start release-specific documentation -->
3177 * <div class="ReleaseSpecificDocumentation">
3178 * <h3>HSQLDB-Specific Information:</h3> <p>
3179 *
3180 * To present, HSQLDB always returns zero, meaning there
3181 * is no limit.
3182 * </div>
3183 * <!-- end release-specific documentation -->
3184 *
3185 * @return the current query timeout limit in seconds; zero means there is
3186 * no limit
3187 * @exception SQLException if a database access error occurs or
3188 * this method is called on a closed <code>Statement</code>
3189 * @see #setQueryTimeout
3190 */
3191 public synchronized int getQueryTimeout() throws SQLException {
3192
3193 if (isClosed || connection.isClosed) {
3194 checkClosed();
3195 }
3196
3197 return queryTimeout;
3198 }
3199
3200 /**
3201 * <!-- start generic documentation -->
3202 * Sets the number of seconds the driver will wait for a
3203 * <code>Statement</code> object to execute to the given number of seconds.
3204 * If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC
3205 * (JDBC4 clarification:)
3206 * driver must apply this limit to the <code>execute</code>,
3207 * <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver
3208 * implementations may also apply this limit to <code>ResultSet</code> methods
3209 * (consult your driver vendor documentation for details).
3210 * <!-- end generic documentation -->
3211 *
3212 * <!-- start release-specific documentation -->
3213 * <div class="ReleaseSpecificDocumentation">
3214 * <h3>HSQLDB-Specific Information:</h3> <p>
3215 *
3216 * The maximum number of seconds to wait is 32767.
3217 * </div>
3218 * <!-- end release-specific documentation -->
3219 *
3220 * @param seconds the new query timeout limit in seconds; zero means
3221 * there is no limit
3222 * @exception SQLException if a database access error occurs,
3223 * this method is called on a closed <code>Statement</code>
3224 * or the condition seconds >= 0 is not satisfied
3225 * @see #getQueryTimeout
3226 */
3227 public synchronized void setQueryTimeout(int seconds) throws SQLException {
3228
3229 if (isClosed || connection.isClosed) {
3230 checkClosed();
3231 }
3232
3233 if (seconds < 0) {
3234 throw JDBCUtil.outOfRangeArgument();
3235 }
3236
3237 if (seconds > Short.MAX_VALUE) {
3238 seconds = Short.MAX_VALUE;
3239 }
3240 queryTimeout = seconds;
3241 }
3242
3243 /**
3244 * <!-- start generic documentation -->
3245 * Cancels this <code>Statement</code> object if both the DBMS and
3246 * driver support aborting an SQL statement.
3247 * This method can be used by one thread to cancel a statement that
3248 * is being executed by another thread.
3249 * <!-- end generic documentation -->
3250 *
3251 * <!-- start release-specific documentation -->
3252 * <div class="ReleaseSpecificDocumentation">
3253 * <h3>HSQLDB-Specific Information:</h3> <p>
3254 *
3255 * HSQLDB version 2.3.4 and later supports aborting an SQL query
3256 * or data update statement.
3257 * </div>
3258 * <!-- end release-specific documentation -->
3259 *
3260 * @exception SQLException if a database access error occurs or
3261 * this method is called on a closed <code>Statement</code>
3262 * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
3263 * this method
3264 */
3265 public void cancel() throws SQLException {
3266 checkClosed();
3267 String sql = resultOut.getMainString();
3268 Result request = Result.newCancelRequest(statementID, sql);
3269
3270 try {
3271 Result response = connection.sessionProxy.cancel(request);
3272 } catch (HsqlException e) {
3273 throw JDBCUtil.sqlException(e);
3274 }
3275
3276 }
3277
3278 /**
3279 * <!-- start generic documentation -->
3280 * Retrieves the first warning reported by calls on this <code>Statement</code> object.
3281 * Subsequent <code>Statement</code> object warnings will be chained to this
3282 * <code>SQLWarning</code> object.
3283 *
3284 * <p>The warning chain is automatically cleared each time
3285 * a statement is (re)executed. This method may not be called on a closed
3286 * <code>Statement</code> object; doing so will cause an <code>SQLException</code>
3287 * to be thrown.
3288 *
3289 * <P><B>Note:</B> If you are processing a <code>ResultSet</code> object, any
3290 * warnings associated with reads on that <code>ResultSet</code> object
3291 * will be chained on it rather than on the <code>Statement</code>
3292 * object that produced it.
3293 * <!-- end generic documentation -->
3294 *
3295 * <!-- start release-specific documentation -->
3296 * <div class="ReleaseSpecificDocumentation">
3297 * <h3>HSQLDB-Specific Information:</h3> <p>
3298 *
3299 * From 1.9 HSQLDB, produces Statement warnings.
3300 * </div>
3301 * <!-- end release-specific documentation -->
3302 *
3303 * @return the first <code>SQLWarning</code> object or <code>null</code>
3304 * if there are no warnings
3305 * @exception SQLException if a database access error occurs or
3306 * this method is called on a closed <code>Statement</code>
3307 */
3308 public synchronized SQLWarning getWarnings() throws SQLException {
3309
3310 if (isClosed || connection.isClosed) {
3311 checkClosed();
3312 }
3313
3314 return rootWarning;
3315 }
3316
3317 /**
3318 * <!-- start generic documentation -->
3319 * Clears all the warnings reported on this <code>Statement</code>
3320 * object. After a call to this method,
3321 * the method <code>getWarnings</code> will return
3322 * <code>null</code> until a new warning is reported for this
3323 * <code>Statement</code> object.
3324 * <!-- end generic documentation -->
3325 *
3326 * <!-- start release-specific documentation -->
3327 * <div class="ReleaseSpecificDocumentation">
3328 * <h3>HSQLDB-Specific Information:</h3> <p>
3329 *
3330 * Supported in HSQLDB 1.9.
3331 * </div>
3332 * <!-- end release-specific documentation -->
3333 *
3334 * @exception SQLException if a database access error occurs or
3335 * this method is called on a closed <code>Statement</code>
3336 */
3337 public synchronized void clearWarnings() throws SQLException {
3338
3339 if (isClosed || connection.isClosed) {
3340 checkClosed();
3341 }
3342 rootWarning = null;
3343 }
3344
3345 /** @todo 1.9.0 - implement */
3346
3347 /**
3348 * <!-- start generic documentation -->
3349 * Sets the SQL cursor name to the given <code>String</code>, which
3350 * will be used by subsequent <code>Statement</code> object
3351 * <code>execute</code> methods. This name can then be
3352 * used in SQL positioned update or delete statements to identify the
3353 * current row in the <code>ResultSet</code> object generated by this
3354 * statement. If the database does not support positioned update/delete,
3355 * this method is a noop. To insure that a cursor has the proper isolation
3356 * level to support updates, the cursor's <code>SELECT</code> statement
3357 * should have the form <code>SELECT FOR UPDATE</code>. If
3358 * <code>FOR UPDATE</code> is not present, positioned updates may fail.
3359 *
3360 * <P><B>Note:</B> By definition, the execution of positioned updates and
3361 * deletes must be done by a different <code>Statement</code> object than
3362 * the one that generated the <code>ResultSet</code> object being used for
3363 * positioning. Also, cursor names must be unique within a connection.
3364 * <!-- end generic documentation -->
3365 *
3366 * <!-- start release-specific documentation -->
3367 * <div class="ReleaseSpecificDocumentation">
3368 * <h3>HSQLDB-Specific Information:</h3> <p>
3369 *
3370 * Including 2.0, HSQLDB does not support named cursors;
3371 * calls to this method are ignored.
3372 * </div>
3373 * <!-- end release-specific documentation -->
3374 *
3375 * @param name the new cursor name, which must be unique within
3376 * a connection
3377 * @exception SQLException if a database access error occurs or
3378 * this method is called on a closed <code>Statement</code>
3379 * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
3380 */
3381 public void setCursorName(String name) throws SQLException {
3382 checkClosed();
3383 }
3384
3385 //----------------------- Multiple Results --------------------------
3386
3387 /**
3388 * <!-- start generic documentation -->
3389 * Retrieves the current result as a <code>ResultSet</code> object.
3390 * This method should be called only once per result.
3391 * <!-- end generic documentation -->
3392 *
3393 * <!-- start release-specific documentation -->
3394 * <div class="ReleaseSpecificDocumentation">
3395 * <h3>HSQLDB-Specific Information:</h3> <p>
3396 *
3397 * Without an interceding call to executeXXX, each invocation of this
3398 * method will produce a new, initialized ResultSet instance referring to
3399 * the current result, if any.
3400 * </div>
3401 * <!-- end release-specific documentation -->
3402 *
3403 * @return the current result as a <code>ResultSet</code> object or
3404 * <code>null</code> if the result is an update count or there are no more results
3405 * @exception SQLException if a database access error occurs or
3406 * this method is called on a closed <code>Statement</code>
3407 * @see #execute
3408 */
3409 public synchronized ResultSet getResultSet() throws SQLException {
3410 return super.getResultSet();
3411 }
3412
3413 /**
3414 * <!-- start generic documentation -->
3415 * Retrieves the current result as an update count;
3416 * if the result is a <code>ResultSet</code> object or there are no more results, -1
3417 * is returned. This method should be called only once per result.
3418 * <!-- end generic documentation -->
3419 *
3420 * @return the current result as an update count; -1 if the current result is a
3421 * <code>ResultSet</code> object or there are no more results
3422 * @exception SQLException if a database access error occurs or
3423 * this method is called on a closed <code>Statement</code>
3424 * @see #execute
3425 */
3426 public synchronized int getUpdateCount() throws SQLException {
3427 return super.getUpdateCount();
3428 }
3429
3430 /**
3431 * <!-- start generic documentation -->
3432 * Moves to this <code>Statement</code> object's next result, returns
3433 * <code>true</code> if it is a <code>ResultSet</code> object, and
3434 * implicitly closes any current <code>ResultSet</code>
3435 * object(s) obtained with the method <code>getResultSet</code>.
3436 *
3437 * <P>There are no more results when the following is true:
3438 * <PRE>
3439 * // stmt is a Statement object
3440 * ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
3441 * </PRE>
3442 * <!-- end generic documentation -->
3443 *
3444 * @return <code>true</code> if the next result is a <code>ResultSet</code>
3445 * object; <code>false</code> if it is an update count or there are
3446 * no more results
3447 * @exception SQLException if a database access error occurs or
3448 * this method is called on a closed <code>Statement</code>
3449 * @see #execute
3450 */
3451 public synchronized boolean getMoreResults() throws SQLException {
3452 return getMoreResults(JDBCStatementBase.CLOSE_CURRENT_RESULT);
3453 }
3454
3455 //--------------------------JDBC 2.0-----------------------------
3456
3457 /**
3458 * <!-- start generic documentation -->
3459 * Gives the driver a hint as to the direction in which
3460 * rows will be processed in <code>ResultSet</code>
3461 * objects created using this <code>Statement</code> object. The
3462 * default value is <code>ResultSet.FETCH_FORWARD</code>.
3463 * <P>
3464 * Note that this method sets the default fetch direction for
3465 * result sets generated by this <code>Statement</code> object.
3466 * Each result set has its own methods for getting and setting
3467 * its own fetch direction.
3468 * <!-- end generic documentation -->
3469 *
3470 * <!-- start release-specific documentation -->
3471 * <div class="ReleaseSpecificDocumentation">
3472 * <h3>HSQLDB-Specific Information:</h3> <p>
3473 *
3474 * Up to 1.8.0.x, HSQLDB supports only <code>FETCH_FORWARD</code>;
3475 * Setting any other value would throw an <code>SQLException</code>
3476 * stating that the operation is not supported. <p>
3477 *
3478 * Starting with 2.0, HSQLDB accepts any valid value.
3479 * </div>
3480 * <!-- end release-specific documentation -->
3481 *
3482 * @param direction the initial direction for processing rows
3483 * @exception SQLException if a database access error occurs,
3484 * this method is called on a closed <code>Statement</code>
3485 * or the given direction
3486 * is not one of <code>ResultSet.FETCH_FORWARD</code>,
3487 * <code>ResultSet.FETCH_REVERSE</code>, or <code>ResultSet.FETCH_UNKNOWN</code>
3488 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3489 * for JDBCStatement)
3490 * @see #getFetchDirection
3491 */
3492 public synchronized void setFetchDirection(
3493 int direction) throws SQLException {
3494
3495 if (isClosed || connection.isClosed) {
3496 checkClosed();
3497 }
3498
3499 if (direction != JDBCResultSet.FETCH_FORWARD
3500 && direction != JDBCResultSet.FETCH_REVERSE
3501 && direction != JDBCResultSet.FETCH_UNKNOWN) {
3502 throw JDBCUtil.notSupported();
3503 }
3504 fetchDirection = direction;
3505 }
3506
3507 /**
3508 * <!-- start generic documentation -->
3509 * Retrieves the direction for fetching rows from
3510 * database tables that is the default for result sets
3511 * generated from this <code>Statement</code> object.
3512 * If this <code>Statement</code> object has not set
3513 * a fetch direction by calling the method <code>setFetchDirection</code>,
3514 * the return value is implementation-specific.
3515 * <!-- end generic documentation -->
3516 *
3517 * <!-- start release-specific documentation -->
3518 * <div class="ReleaseSpecificDocumentation">
3519 * <h3>HSQLDB-Specific Information:</h3> <p>
3520 *
3521 * Up to 1.8.0.x, HSQLDB always returned FETCH_FORWARD.
3522 *
3523 * Starting with 2.0, HSQLDB returns FETCH_FORWARD by default, or
3524 * whatever value has been explicitly assigned by invoking
3525 * <code>setFetchDirection</code>.
3526 * .
3527 * </div>
3528 * <!-- end release-specific documentation -->
3529 *
3530 * @return the default fetch direction for result sets generated
3531 * from this <code>Statement</code> object
3532 * @exception SQLException if a database access error occurs or
3533 * this method is called on a closed <code>Statement</code>
3534 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3535 * for JDBCStatement)
3536 * @see #setFetchDirection
3537 */
3538 public synchronized int getFetchDirection() throws SQLException {
3539
3540 if (isClosed || connection.isClosed) {
3541 checkClosed();
3542 }
3543
3544 return fetchDirection;
3545 }
3546
3547 /**
3548 * <!-- start generic documentation -->
3549 * (JDBC4 clarification:)
3550 * Gives the JDBC driver a hint as to the number of rows that should
3551 * be fetched from the database when more rows are needed for
3552 * <code>ResultSet</code> objects generated by this <code>Statement</code>.
3553 * If the value specified is zero, then the hint is ignored.
3554 * The default value is zero.
3555 * <!-- start generic documentation -->
3556 *
3557 * <!-- start release-specific documentation -->
3558 * <div class="ReleaseSpecificDocumentation">
3559 * <h3>HSQLDB-Specific Information:</h3> <p>
3560 *
3561 * HSQLDB uses the specified value as a hint, but may process more or fewer
3562 * rows than specified.
3563 * </div>
3564 * <!-- end release-specific documentation -->
3565 *
3566 * @param rows the number of rows to fetch
3567 * @exception SQLException if a database access error occurs,
3568 * this method is called on a closed <code>Statement</code> or the
3569 * (JDBC4 modified:)
3570 * condition <code>rows >= 0</code> is not satisfied.
3571 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3572 * for JDBCStatement)
3573 * @see #getFetchSize
3574 */
3575 public synchronized void setFetchSize(int rows) throws SQLException {
3576
3577 if (isClosed || connection.isClosed) {
3578 checkClosed();
3579 }
3580
3581 if (rows < 0) {
3582 throw JDBCUtil.outOfRangeArgument();
3583 }
3584 fetchSize = rows;
3585 }
3586
3587 /**
3588 * <!-- start generic documentation -->
3589 * Retrieves the number of result set rows that is the default
3590 * fetch size for <code>ResultSet</code> objects
3591 * generated from this <code>Statement</code> object.
3592 * If this <code>Statement</code> object has not set
3593 * a fetch size by calling the method <code>setFetchSize</code>,
3594 * the return value is implementation-specific.
3595 * <!-- end generic documentation -->
3596 *
3597 * <!-- start release-specific documentation -->
3598 * <div class="ReleaseSpecificDocumentation">
3599 * <b>HSQLDB-Specific Information</b> <p>
3600 *
3601 * HSQLDB returns 0 by default, or the fetch size specified by setFetchSize
3602 * </div>
3603 * <!-- end release-specific documentation -->
3604 *
3605 * @return the default fetch size for result sets generated
3606 * from this <code>Statement</code> object
3607 * @exception SQLException if a database access error occurs or
3608 * this method is called on a closed <code>Statement</code>
3609 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3610 * for JDBCStatement)
3611 * @see #setFetchSize
3612 */
3613 public synchronized int getFetchSize() throws SQLException {
3614
3615 if (isClosed || connection.isClosed) {
3616 checkClosed();
3617 }
3618
3619 return fetchSize;
3620 }
3621
3622 /**
3623 * <!-- start generic documentation -->
3624 * Retrieves the result set concurrency for <code>ResultSet</code> objects
3625 * generated by this <code>Statement</code> object.
3626 * <!-- end generic documentation -->
3627 *
3628 * <!-- start release-specific documentation -->
3629 * <div class="ReleaseSpecificDocumentation">
3630 * <h3>HSQLDB-Specific Information:</h3> <p>
3631 *
3632 * HSQLDB supports <code>CONCUR_READ_ONLY</code> and
3633 * <code>CONCUR_READ_UPDATEBLE</code> concurrency.
3634 * </div>
3635 * <!-- end release-specific documentation -->
3636 *
3637 * @return either <code>ResultSet.CONCUR_READ_ONLY</code> or
3638 * <code>ResultSet.CONCUR_UPDATABLE</code>
3639 * @exception SQLException if a database access error occurs or
3640 * this method is called on a closed <code>Statement</code>
3641 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3642 * for JDBCStatement)
3643 */
3644 public synchronized int getResultSetConcurrency() throws SQLException {
3645
3646 if (isClosed || connection.isClosed) {
3647 checkClosed();
3648 }
3649
3650 return ResultProperties.getJDBCConcurrency(rsProperties);
3651 }
3652
3653 /**
3654 * <!-- start generic documentation -->
3655 * Retrieves the result set type for <code>ResultSet</code> objects
3656 * generated by this <code>Statement</code> object.
3657 * <!-- end generic documentation -->
3658 *
3659 * <!-- start release-specific documentation -->
3660 * <div class="ReleaseSpecificDocumentation">
3661 * <h3>HSQLDB-Specific Information:</h3> <p>
3662 *
3663 * HSQLDB 1.7.0 and later versions support <code>TYPE_FORWARD_ONLY</code>
3664 * and <code>TYPE_SCROLL_INSENSITIVE</code>.
3665 * </div>
3666 * <!-- end release-specific documentation -->
3667 *
3668 * @return one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
3669 * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
3670 * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
3671 * @exception SQLException if a database access error occurs or
3672 * this method is called on a closed <code>Statement</code>
3673 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3674 * for JDBCStatement)
3675 */
3676 public synchronized int getResultSetType() throws SQLException {
3677
3678 // fredt - omit checkClosed() in order to be able to handle the result of a
3679 // SHUTDOWN query
3680 if (isClosed || connection.isClosed) {
3681 checkClosed();
3682 }
3683
3684 return ResultProperties.getJDBCScrollability(rsProperties);
3685 }
3686
3687 /**
3688 * <!-- start generic documentation -->
3689 * Empties this <code>Statement</code> object's current list of
3690 * SQL commands.
3691 * <P>
3692 * (JDBC4 clarification:) <p>
3693 * <B>NOTE:</B> Support of an ability to batch updates is optional.
3694 * <!-- start generic documentation -->
3695 *
3696 * <!-- start release-specific documentation -->
3697 * <div class="ReleaseSpecificDocumentation">
3698 * <h3>HSQLDB-Specific Information:</h3> <p>
3699 *
3700 * Starting with HSQLDB 1.7.2, this feature is supported.
3701 * </div>
3702 * <!-- end release-specific documentation -->
3703 *
3704 * @exception SQLException if a database access error occurs,
3705 * this method is called on a closed <code>Statement</code> or the
3706 * driver does not support batch updates
3707 * @see #addBatch
3708 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3709 * for JDBCStatement)
3710 */
3711 public synchronized void clearBatch() throws SQLException {
3712
3713 if (isClosed || connection.isClosed) {
3714 checkClosed();
3715 }
3716
3717 if (isBatch) {
3718 resultOut.getNavigator().clear();
3719 }
3720 }
3721
3722 /**
3723 * <!-- start generic documentation -->
3724 * Retrieves the <code>Connection</code> object
3725 * that produced this <code>Statement</code> object.
3726 * <!-- end generic documentation -->
3727 *
3728 * @return the connection that produced this statement
3729 * @exception SQLException if a database access error occurs or
3730 * this method is called on a closed <code>Statement</code>
3731 * @since JDK 1.2 (JDK 1.1.x developers: read the overview
3732 * for JDBCStatement)
3733 */
3734 public synchronized Connection getConnection() throws SQLException {
3735
3736 if (isClosed || connection.isClosed) {
3737 checkClosed();
3738 }
3739
3740 return connection;
3741 }
3742
3743 //----------------------------- JDBC 4.0 -----------------------------------
3744 // --------------------------- Added: Mustang Build 81 -------------------------
3745 boolean poolable = true;
3746
3747 /**
3748 * Requests that a <code>Statement</code> be pooled or not pooled. The value
3749 * specified is a hint to the statement pool implementation indicating
3750 * whether the application wants the statement to be pooled. It is up to
3751 * the statement pool manager as to whether the hint is used.
3752 * <p>
3753 * The poolable value of a statement is applicable to both internal
3754 * statement caches implemented by the driver and external statement caches
3755 * implemented by application servers and other applications.
3756 * <p>
3757 * By default, a <code>Statement</code> is not poolable when created, and
3758 * a <code>PreparedStatement</code> and <code>CallableStatement</code>
3759 * are poolable when created.
3760 * <p>
3761 * @param poolable requests that the statement be pooled if true and
3762 * that the statement not be pooled if false
3763 * <p>
3764 * @throws SQLException if this method is called on a closed
3765 * <code>Statement</code>
3766 * <p>
3767 * @since JDK 1.6 Build 81, HSQLDB 2.0
3768 */
3769 public synchronized void setPoolable(
3770 boolean poolable) throws SQLException {
3771
3772 if (isClosed || connection.isClosed) {
3773 checkClosed();
3774 }
3775 this.poolable = poolable;
3776 }
3777
3778 /**
3779 * Returns a value indicating whether the <code>Statement</code>
3780 * is poolable or not.
3781 * <p>
3782 * @return <code>true</code> if the <code>Statement</code>
3783 * is poolable; <code>false</code> otherwise
3784 * @throws SQLException if this method is called on a closed
3785 * <code>Statement</code>
3786 * <p>
3787 * @since JDK 1.6 Build 81, HSQLDB 2.0
3788 * <p>
3789 * @see #setPoolable(boolean) setPoolable(boolean)
3790 */
3791 public synchronized boolean isPoolable() throws SQLException {
3792
3793 if (isClosed || connection.isClosed) {
3794 checkClosed();
3795 }
3796
3797 return this.poolable;
3798 }
3799
3800 // ------------------- java.sql.Wrapper implementation ---------------------
3801
3802 /**
3803 * Returns an object that implements the given interface to allow access to
3804 * non-standard methods, or standard methods not exposed by the proxy.
3805 *
3806 * If the receiver implements the interface then the result is the receiver
3807 * or a proxy for the receiver. If the receiver is a wrapper
3808 * and the wrapped object implements the interface then the result is the
3809 * wrapped object or a proxy for the wrapped object. Otherwise return the
3810 * the result of calling <code>unwrap</code> recursively on the wrapped object
3811 * or a proxy for that result. If the receiver is not a
3812 * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
3813 *
3814 * @param iface A Class defining an interface that the result must implement.
3815 * @return an object that implements the interface. May be a proxy for the actual implementing object.
3816 * @throws java.sql.SQLException If no object found that implements the interface
3817 * @since JDK 1.6, HSQLDB 2.0
3818 */
3819 //#ifdef JAVA6
3820 @SuppressWarnings("unchecked")
3821 public <T>T unwrap(Class<T> iface) throws java.sql.SQLException {
3822
3823 if (isWrapperFor(iface)) {
3824 return (T) this;
3825 }
3826
3827 throw JDBCUtil.invalidArgument("iface: " + iface);
3828 }
3829
3830 //#endif JAVA6
3831
3832 /**
3833 * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
3834 * for an object that does. Returns false otherwise. If this implements the interface then return true,
3835 * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
3836 * object. If this does not implement the interface and is not a wrapper, return false.
3837 * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
3838 * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
3839 * returns true then calling <code>unwrap</code> with the same argument should succeed.
3840 *
3841 * @param iface a Class defining an interface.
3842 * @return true if this implements the interface or directly or indirectly wraps an object that does.
3843 * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper
3844 * for an object with the given interface.
3845 * @since JDK 1.6, HSQLDB 2.0
3846 */
3847 //#ifdef JAVA6
3848 public boolean isWrapperFor(
3849 java.lang.Class<?> iface) throws java.sql.SQLException {
3850 return (iface != null && iface.isAssignableFrom(this.getClass()));
3851 }
3852
3853 //#endif JAVA6
3854 //-------------------- Internal Implementation -----------------------------
3855
3856 /**
3857 * Constructs a statement that produces results of the requested
3858 * <code>type</code>. <p>
3859 *
3860 * A prepared statement must be a single SQL statement. <p>
3861 *
3862 * @param c the Connection used execute this statement
3863 * @param sql the SQL statement this object represents
3864 * @param resultSetType the type of result this statement will produce (scrollability)
3865 * @param resultSetConcurrency (updatability)
3866 * @param resultSetHoldability (validity beyond commit)
3867 * @param generatedKeys internal mode of handling generated key reporting
3868 * @param generatedIndexes column indexes for generated keys
3869 * @param generatedNames column names for generated keys are given
3870 * @throws HsqlException if the statement is not accepted by the database
3871 * @throws SQLException if preprocessing by driver fails
3872 */
3873 JDBCPreparedStatement(JDBCConnection c, String sql, int resultSetType,
3874 int resultSetConcurrency, int resultSetHoldability,
3875 int generatedKeys, int[] generatedIndexes,
3876 String[] generatedNames) throws HsqlException,
3877 SQLException {
3878
3879 isResult = false;
3880 connection = c;
3881 connectionIncarnation = connection.incarnation;
3882 session = c.sessionProxy;
3883 sql = c.nativeSQL(sql);
3884
3885 resultOut = Result.newPrepareStatementRequest();
3886
3887 int props = ResultProperties.getValueForJDBC(resultSetType,
3888 resultSetConcurrency, resultSetHoldability);
3889
3890 resultOut.setPrepareOrExecuteProperties(sql, 0, 0, 0, queryTimeout,
3891 props, generatedKeys, generatedIndexes, generatedNames);
3892
3893 Result in = session.execute(resultOut);
3894
3895 if (in.mode == ResultConstants.ERROR) {
3896 throw JDBCUtil.sqlException(in);
3897 }
3898 rootWarning = null;
3899
3900 Result current = in;
3901
3902 while (current.getChainedResult() != null) {
3903 current = current.getUnlinkChainedResult();
3904
3905 if (current.isWarning()) {
3906 SQLWarning w = JDBCUtil.sqlWarning(current);
3907
3908 if (rootWarning == null) {
3909 rootWarning = w;
3910 } else {
3911 rootWarning.setNextWarning(w);
3912 }
3913 }
3914 }
3915 connection.setWarnings(rootWarning);
3916
3917 statementID = in.getStatementID();
3918 statementRetType = in.getStatementType();
3919 resultMetaData = in.metaData;
3920 parameterMetaData = in.parameterMetaData;
3921 parameterTypes = parameterMetaData.getParameterTypes();
3922 parameterModes = parameterMetaData.paramModes;
3923 rsProperties = in.rsProperties;
3924
3925 //
3926 int paramCount = parameterMetaData.getColumnCount();
3927
3928 parameterValues = new Object[paramCount];
3929 parameterSet = new Boolean[paramCount];
3930 streamLengths = new long[paramCount];
3931
3932 //
3933 //
3934 for (int i = 0; i < paramCount; i++) {
3935 if (parameterTypes[i].isLobType()) {
3936 hasLOBs = true;
3937
3938 break;
3939 }
3940 }
3941
3942 //
3943 resultOut = Result.newPreparedExecuteRequest(parameterTypes,
3944 statementID);
3945
3946 resultOut.setStatement(in.getStatement());
3947
3948 // for toString()
3949 this.sql = sql;
3950 }
3951
3952 /**
3953 * Constructor for updatable ResultSet
3954 */
3955 JDBCPreparedStatement(JDBCConnection c, Result result) {
3956
3957 isResult = true;
3958 connection = c;
3959 connectionIncarnation = connection.incarnation;
3960 session = c.sessionProxy;
3961
3962 int paramCount = result.metaData.getExtendedColumnCount();
3963
3964 parameterMetaData = result.metaData;
3965 parameterTypes = result.metaData.columnTypes;
3966 parameterModes = new byte[paramCount];
3967 parameterValues = new Object[paramCount];
3968 parameterSet = new Boolean[paramCount];
3969 streamLengths = new long[paramCount];
3970
3971 //
3972 for (int i = 0; i < paramCount; i++) {
3973 parameterModes[i] = SchemaObject.ParameterModes.PARAM_IN;
3974
3975 if (parameterTypes[i].isLobType()) {
3976 hasLOBs = true;
3977 }
3978 }
3979
3980 //
3981 resultOut = Result.newUpdateResultRequest(parameterTypes,
3982 result.getResultId());
3983 }
3984
3985 /**
3986 * Checks if execution does or does not generate a single row
3987 * update count, throwing if the argument, yes, does not match. <p>
3988 *
3989 * @param type type of statement regarding what it returns
3990 * something other than a single row update count.
3991 * @throws SQLException if the argument, yes, does not match
3992 */
3993 protected void checkStatementType(int type) throws SQLException {
3994
3995 if (type != statementRetType) {
3996 if (statementRetType == StatementTypes.RETURN_COUNT) {
3997 throw JDBCUtil.sqlException(ErrorCode.X_07504);
3998 } else {
3999 throw JDBCUtil.sqlException(ErrorCode.X_07503);
4000 }
4001 }
4002 }
4003
4004 protected void checkParameterIndex(int i) throws SQLException {
4005
4006 if (isClosed || connection.isClosed) {
4007 checkClosed();
4008 }
4009
4010 if (i < 1 || i > parameterValues.length) {
4011 String msg = "parameter index out of range: " + i;
4012
4013 throw JDBCUtil.outOfRangeArgument(msg);
4014 }
4015 }
4016
4017 /**
4018 * Checks if the specified parameter index value is valid in terms of
4019 * setting an IN or IN OUT parameter value. <p>
4020 *
4021 * @param i The parameter index to check
4022 * @throws SQLException if the specified parameter index is invalid
4023 */
4024 protected void checkSetParameterIndex(int i) throws SQLException {
4025
4026 if (isClosed || connection.isClosed) {
4027 checkClosed();
4028 }
4029
4030 if (i < 1 || i > parameterValues.length) {
4031 String msg = "parameter index out of range: " + i;
4032
4033 throw JDBCUtil.outOfRangeArgument(msg);
4034 }
4035
4036 if (parameterModes[i - 1] == SchemaObject.ParameterModes.PARAM_OUT) {
4037 String msg = "Not IN or INOUT mode for parameter: " + i;
4038
4039 throw JDBCUtil.invalidArgument(msg);
4040 }
4041 }
4042
4043 /**
4044 * Checks if the specified parameter index value is valid in terms of
4045 * getting an OUT or INOUT parameter value. <p>
4046 *
4047 * @param i The parameter index to check
4048 * @throws SQLException if the specified parameter index is invalid
4049 */
4050 protected void checkGetParameterIndex(int i) throws SQLException {
4051
4052 String msg;
4053
4054 if (isClosed || connection.isClosed) {
4055 checkClosed();
4056 }
4057
4058 if (i < 1 || i > parameterValues.length) {
4059 msg = "parameter index out of range: " + i;
4060
4061 throw JDBCUtil.outOfRangeArgument(msg);
4062 }
4063
4064 int mode = parameterModes[i - 1];
4065
4066 switch (mode) {
4067
4068 case SchemaObject.ParameterModes.PARAM_UNKNOWN :
4069 case SchemaObject.ParameterModes.PARAM_OUT :
4070 case SchemaObject.ParameterModes.PARAM_INOUT :
4071 break;
4072 case SchemaObject.ParameterModes.PARAM_IN :
4073 default :
4074 msg = "Not OUT or INOUT mode: " + mode + " for parameter: "
4075 + i;
4076
4077 throw JDBCUtil.invalidArgument(msg);
4078 }
4079 }
4080
4081 /**
4082 * Called just before execution or adding to batch, this ensures all the
4083 * parameters have been set.<p>
4084 *
4085 * If a parameter has been set using a stream method, it should be set
4086 * again for the next reuse. When set using other methods, the parameter
4087 * setting is retained for the next use.
4088 * @throws SQLException
4089 */
4090 private void checkParametersSet() throws SQLException {
4091
4092 if (isResult) {
4093 return;
4094 }
4095
4096 for (int i = 0; i < parameterSet.length; i++) {
4097 if (parameterModes[i] != SchemaObject.ParameterModes.PARAM_OUT) {
4098 if (parameterSet[i] == null) {
4099 throw JDBCUtil.sqlException(ErrorCode.JDBC_PARAMETER_NOT_SET);
4100 }
4101 }
4102 }
4103 }
4104
4105 /**
4106 * The internal parameter value setter always converts the parameter to
4107 * the Java type required for data transmission.
4108 *
4109 * @param i parameter index
4110 * @param o object
4111 * @throws SQLException if either argument is not acceptable.
4112 */
4113 void setParameter(int i, Object o) throws SQLException {
4114
4115 checkSetParameterIndex(i);
4116
4117 i--;
4118
4119 if (o == null) {
4120 parameterValues[i] = null;
4121 parameterSet[i] = Boolean.TRUE;
4122
4123 return;
4124 }
4125
4126 Type outType = parameterTypes[i];
4127
4128 switch (outType.typeCode) {
4129
4130 case Types.OTHER :
4131 try {
4132 if (connection.isStoreLiveObject) {
4133 o = new JavaObjectDataInternal(o);
4134
4135 break;
4136 }
4137
4138 if (o instanceof Serializable) {
4139 o = new JavaObjectData((Serializable) o);
4140
4141 break;
4142 }
4143 } catch (HsqlException e) {
4144 JDBCUtil.throwError(e);
4145 }
4146 JDBCUtil.throwError(Error.error(ErrorCode.X_42563));
4147 case Types.SQL_BIT :
4148 case Types.SQL_BIT_VARYING :
4149 try {
4150 if (o instanceof Boolean) {
4151 o = outType.convertToDefaultType(session, o);
4152
4153 break;
4154 }
4155
4156 if (o instanceof Integer) {
4157 o = outType.convertToDefaultType(session, o);
4158
4159 break;
4160 }
4161
4162 if (o instanceof byte[]) {
4163 o = outType.convertToDefaultType(session, o);
4164
4165 break;
4166 }
4167
4168 if (o instanceof String) {
4169 o = outType.convertToDefaultType(session, o);
4170
4171 break;
4172 }
4173 } catch (HsqlException e) {
4174 JDBCUtil.throwError(e);
4175 }
4176 JDBCUtil.throwError(Error.error(ErrorCode.X_42563));
4177
4178 // fall through
4179 case Types.SQL_BINARY :
4180 case Types.SQL_VARBINARY :
4181 case Types.SQL_GUID :
4182 if (o instanceof byte[]) {
4183 o = new BinaryData((byte[]) o, !connection.isNetConn);
4184
4185 break;
4186 }
4187
4188 if (o instanceof UUID) {
4189 o = BinaryUUIDType.getBinary((UUID) o);
4190 break;
4191 }
4192
4193 try {
4194 if (o instanceof String) {
4195 o = outType.convertToDefaultType(session, o);
4196
4197 break;
4198 }
4199 } catch (HsqlException e) {
4200 JDBCUtil.throwError(e);
4201 }
4202 JDBCUtil.throwError(Error.error(ErrorCode.X_42563));
4203
4204 break;
4205 case Types.SQL_ARRAY :
4206 if (o instanceof Array) {
4207 setArray(i + 1, (Array) o);
4208
4209 return;
4210 }
4211
4212 if (o instanceof ArrayList) {
4213 o = ((ArrayList) o).toArray();
4214 }
4215
4216 if (o instanceof Object[]) {
4217 Type baseType = outType.collectionBaseType();
4218 Object[] array = (Object[]) o;
4219 Object[] data = new Object[array.length];
4220
4221 for (int j = 0; j < data.length; j++) {
4222 data[j] = baseType.convertJavaToSQL(session, array[j]);
4223 }
4224 o = data;
4225
4226 break;
4227 }
4228 JDBCUtil.throwError(Error.error(ErrorCode.X_42563));
4229 case Types.SQL_BLOB :
4230 setBlobParameter(i + 1, o);
4231
4232 return;
4233 case Types.SQL_CLOB :
4234 setClobParameter(i + 1, o);
4235
4236 return;
4237 case Types.SQL_DATE :
4238 case Types.SQL_TIME_WITH_TIME_ZONE :
4239 case Types.SQL_TIMESTAMP_WITH_TIME_ZONE :
4240 case Types.SQL_TIME :
4241 case Types.SQL_TIMESTAMP : {
4242 try {
4243 if (o instanceof String) {
4244 o = outType.convertToType(session, o,
4245 Type.SQL_VARCHAR);
4246
4247 break;
4248 }
4249 o = outType.convertJavaToSQL(session, o);
4250
4251 break;
4252 } catch (HsqlException e) {
4253 JDBCUtil.throwError(e);
4254 }
4255 }
4256 case Types.TINYINT :
4257 case Types.SQL_SMALLINT :
4258 case Types.SQL_INTEGER :
4259 case Types.SQL_BIGINT :
4260 case Types.SQL_REAL :
4261 case Types.SQL_FLOAT :
4262 case Types.SQL_DOUBLE :
4263 case Types.SQL_NUMERIC :
4264 case Types.SQL_DECIMAL :
4265 try {
4266 if (o instanceof String) {
4267 o = outType.convertToType(session, o,
4268 Type.SQL_VARCHAR);
4269
4270 break;
4271 } else if (o instanceof Boolean) {
4272 boolean value = ((Boolean) o).booleanValue();
4273
4274 o = value ? Integer.valueOf(1)
4275 : Integer.valueOf(0);
4276 }
4277 o = outType.convertToDefaultType(session, o);
4278
4279 break;
4280 } catch (HsqlException e) {
4281 JDBCUtil.throwError(e);
4282 }
4283 case Types.SQL_VARCHAR : {
4284 if (o instanceof String) {
4285 break;
4286 } else {
4287 try {
4288 o = outType.convertToDefaultType(session, o);
4289
4290 break;
4291 } catch (HsqlException e) {
4292 JDBCUtil.throwError(e);
4293 }
4294 }
4295 }
4296 case Types.SQL_CHAR :
4297 if (outType.precision == 1) {
4298 if (o instanceof Character) {
4299 o = new String(new char[] {
4300 ((Character) o).charValue() });
4301
4302 break;
4303 } else if (o instanceof Boolean) {
4304 o = ((Boolean) o).booleanValue() ? "1"
4305 : "0";
4306
4307 break;
4308 }
4309 }
4310
4311 // fall through
4312 default :
4313 try {
4314 o = outType.convertToDefaultType(session, o);
4315
4316 break;
4317 } catch (HsqlException e) {
4318 JDBCUtil.throwError(e);
4319 }
4320 }
4321 parameterValues[i] = o;
4322 parameterSet[i] = Boolean.TRUE;
4323 }
4324
4325 /**
4326 * setParameterForClob
4327 *
4328 * @param i int
4329 * @param o Object
4330 * @throws SQLException
4331 */
4332 void setClobParameter(int i, Object o) throws SQLException {
4333 setClobParameter(i, o, 0);
4334 }
4335
4336 void setClobParameter(int i, Object o,
4337 long streamLength) throws SQLException {
4338
4339 if (o instanceof JDBCClobClient) {
4340 JDBCClobClient clob = (JDBCClobClient) o;
4341
4342 if (!clob.session.getDatabaseUniqueName().equals(
4343 session.getDatabaseUniqueName())) {
4344 streamLength = clob.length();
4345
4346 Reader is = clob.getCharacterStream();
4347
4348 parameterValues[i - 1] = is;
4349 streamLengths[i - 1] = streamLength;
4350 parameterSet[i - 1] = Boolean.FALSE;
4351
4352 return;
4353 }
4354 parameterValues[i - 1] = o;
4355 parameterSet[i - 1] = Boolean.TRUE;
4356
4357 return;
4358 } else if (o instanceof Clob) {
4359 parameterValues[i - 1] = o;
4360 parameterSet[i - 1] = Boolean.TRUE;
4361
4362 return;
4363 } else if (o instanceof ClobInputStream) {
4364 ClobInputStream is = (ClobInputStream) o;
4365
4366 if (is.session.getDatabaseUniqueName().equals(
4367 session.getDatabaseUniqueName())) {
4368 throw JDBCUtil.sqlException(ErrorCode.JDBC_INVALID_ARGUMENT,
4369 "invalid Reader");
4370 }
4371 parameterValues[i - 1] = o;
4372 streamLengths[i - 1] = streamLength;
4373 parameterSet[i - 1] = Boolean.FALSE;
4374
4375 return;
4376 } else if (o instanceof Reader) {
4377 parameterValues[i - 1] = o;
4378 streamLengths[i - 1] = streamLength;
4379 parameterSet[i - 1] = Boolean.FALSE;
4380
4381 return;
4382 } else if (o instanceof String) {
4383 JDBCClob clob = new JDBCClob((String) o);
4384
4385 parameterValues[i - 1] = clob;
4386 parameterSet[i - 1] = Boolean.FALSE;
4387
4388 return;
4389 }
4390
4391 throw JDBCUtil.invalidArgument();
4392 }
4393
4394 /**
4395 * setParameterForBlob
4396 *
4397 * @param i int
4398 * @param o Object
4399 */
4400 void setBlobParameter(int i, Object o) throws SQLException {
4401 setBlobParameter(i, o, 0);
4402 }
4403
4404 void setBlobParameter(int i, Object o,
4405 long streamLength) throws SQLException {
4406
4407 if (o instanceof JDBCBlobClient) {
4408 JDBCBlobClient blob = (JDBCBlobClient) o;
4409
4410 if (!blob.session.getDatabaseUniqueName().equals(
4411 session.getDatabaseUniqueName())) {
4412 streamLength = blob.length();
4413
4414 InputStream is = blob.getBinaryStream();
4415
4416 parameterValues[i - 1] = is;
4417 streamLengths[i - 1] = streamLength;
4418 parameterSet[i - 1] = Boolean.FALSE;
4419
4420 return;
4421 }
4422
4423 // in the same database
4424 parameterValues[i - 1] = o;
4425 parameterSet[i - 1] = Boolean.TRUE;
4426
4427 return;
4428 } else if (o instanceof Blob) {
4429 parameterValues[i - 1] = o;
4430 parameterSet[i - 1] = Boolean.FALSE;
4431
4432 return;
4433 } else if (o instanceof BlobInputStream) {
4434 BlobInputStream is = (BlobInputStream) o;
4435
4436 if (is.session.getDatabaseUniqueName().equals(
4437 session.getDatabaseUniqueName())) {
4438 throw JDBCUtil.sqlException(ErrorCode.JDBC_INVALID_ARGUMENT,
4439 "invalid Reader");
4440 }
4441
4442 // in the same database ? see if it blocks in
4443 parameterValues[i - 1] = o;
4444 streamLengths[i - 1] = streamLength;
4445 parameterSet[i - 1] = Boolean.FALSE;
4446
4447 return;
4448 } else if (o instanceof InputStream) {
4449 parameterValues[i - 1] = o;
4450 streamLengths[i - 1] = streamLength;
4451 parameterSet[i - 1] = Boolean.FALSE;
4452
4453 return;
4454 } else if (o instanceof byte[]) {
4455 JDBCBlob blob = new JDBCBlob((byte[]) o);
4456
4457 parameterValues[i - 1] = blob;
4458 parameterSet[i - 1] = Boolean.TRUE;
4459
4460 return;
4461 }
4462
4463 throw JDBCUtil.invalidArgument();
4464 }
4465
4466 /**
4467 * Used with int and narrower integral primitives
4468 * @param i parameter index
4469 * @param value object to set
4470 * @throws SQLException if either argument is not acceptable
4471 */
4472 void setIntParameter(int i, int value) throws SQLException {
4473
4474 checkSetParameterIndex(i);
4475
4476 int outType = parameterTypes[i - 1].typeCode;
4477
4478 switch (outType) {
4479
4480 case Types.TINYINT :
4481 case Types.SQL_SMALLINT :
4482 case Types.SQL_INTEGER : {
4483 Object o = Integer.valueOf(value);
4484
4485 parameterValues[i - 1] = o;
4486 parameterSet[i - 1] = Boolean.TRUE;
4487
4488 break;
4489 }
4490 case Types.SQL_BIGINT : {
4491 Object o = Long.valueOf(value);
4492
4493 parameterValues[i - 1] = o;
4494 parameterSet[i - 1] = Boolean.TRUE;
4495
4496 break;
4497 }
4498 case Types.SQL_BINARY :
4499 case Types.SQL_VARBINARY :
4500 case Types.OTHER :
4501 throw JDBCUtil.sqlException(Error.error(ErrorCode.X_42563));
4502 default :
4503 setParameter(i, Integer.valueOf(value));
4504 }
4505 }
4506
4507 /**
4508 * Used with long and narrower integral primitives. Conversion to BINARY
4509 * or OTHER types will throw here and not passed to setParameter().
4510 *
4511 * @param i parameter index
4512 * @param value object to set
4513 * @throws SQLException if either argument is not acceptable
4514 */
4515 void setLongParameter(int i, long value) throws SQLException {
4516
4517 checkSetParameterIndex(i);
4518
4519 int outType = parameterTypes[i - 1].typeCode;
4520
4521 switch (outType) {
4522
4523 case Types.SQL_BIGINT :
4524 Object o = Long.valueOf(value);
4525
4526 parameterValues[i - 1] = o;
4527 parameterSet[i - 1] = Boolean.TRUE;
4528
4529 break;
4530 case Types.SQL_BINARY :
4531 case Types.SQL_VARBINARY :
4532 case Types.OTHER :
4533 throw JDBCUtil.sqlException(Error.error(ErrorCode.X_42563));
4534 default :
4535 setParameter(i, Long.valueOf(value));
4536 }
4537 }
4538
4539 private void performPreExecute() throws SQLException, HsqlException {
4540
4541 if (!hasLOBs) {
4542 return;
4543 }
4544
4545 for (int i = 0; i < parameterValues.length; i++) {
4546 Object value = parameterValues[i];
4547
4548 if (value == null) {
4549 continue;
4550 }
4551
4552 if (parameterTypes[i].typeCode == Types.SQL_BLOB) {
4553 long id;
4554 BlobDataID blob = null;
4555
4556 if (value instanceof JDBCBlobClient) {
4557
4558 // check or fix id mismatch
4559 blob = ((JDBCBlobClient) value).blob;
4560 id = blob.getId();
4561 } else if (value instanceof Blob) {
4562 long length = ((Blob) value).length();
4563
4564 blob = session.createBlob(length);
4565 id = blob.getId();
4566
4567 InputStream stream = ((Blob) value).getBinaryStream();
4568 ResultLob resultLob =
4569 ResultLob.newLobCreateBlobRequest(session.getId(), id,
4570 stream, length);
4571
4572 session.allocateResultLob(resultLob, null);
4573 resultOut.addLobResult(resultLob);
4574 } else if (value instanceof InputStream) {
4575 long length = streamLengths[i];
4576
4577 long createLength = length > 0 ? length : 0;
4578
4579 blob = session.createBlob(createLength);
4580 id = blob.getId();
4581
4582 InputStream stream = (InputStream) value;
4583 ResultLob resultLob =
4584 ResultLob.newLobCreateBlobRequest(session.getId(), id,
4585 stream, length);
4586
4587 session.allocateResultLob(resultLob, null);
4588 resultOut.addLobResult(resultLob);
4589 } else if (value instanceof BlobDataID) {
4590 blob = (BlobDataID) value;
4591 }
4592 parameterValues[i] = blob;
4593 } else if (parameterTypes[i].typeCode == Types.SQL_CLOB) {
4594 long id;
4595 ClobDataID clob = null;
4596
4597 if (value instanceof JDBCClobClient) {
4598
4599 // check or fix id mismatch
4600 clob = ((JDBCClobClient) value).clob;
4601 id = clob.getId();
4602 } else if (value instanceof Clob) {
4603 long length = ((Clob) value).length();
4604 Reader reader = ((Clob) value).getCharacterStream();
4605
4606 clob = session.createClob(length);
4607 id = clob.getId();
4608
4609 ResultLob resultLob =
4610 ResultLob.newLobCreateClobRequest(session.getId(), id,
4611 reader, length);
4612
4613 session.allocateResultLob(resultLob, null);
4614 resultOut.addLobResult(resultLob);
4615 } else if (value instanceof Reader) {
4616 long length = streamLengths[i];
4617
4618 long createLength = length > 0 ? length : 0;
4619
4620 clob = session.createClob(createLength);
4621 id = clob.getId();
4622
4623 Reader reader = (Reader) value;
4624 ResultLob resultLob =
4625 ResultLob.newLobCreateClobRequest(session.getId(), id,
4626 reader, length);
4627
4628 session.allocateResultLob(resultLob, null);
4629 resultOut.addLobResult(resultLob);
4630 } else if (value instanceof ClobDataID) {
4631 clob = (ClobDataID) value;
4632 }
4633 parameterValues[i] = clob;
4634 }
4635 }
4636 }
4637
4638 /**
4639 * Internal result producer for JDBCStatement (sqlExecDirect mode).
4640 * <p>
4641 *
4642 * @throws SQLException when a database access error occurs
4643 */
4644 void fetchResult() throws SQLException {
4645
4646 if (isClosed || connection.isClosed) {
4647 checkClosed();
4648 }
4649 closeResultData();
4650 checkParametersSet();
4651
4652 if (isBatch) {
4653 throw JDBCUtil.sqlExceptionSQL(ErrorCode.X_07505);
4654 }
4655
4656 //
4657 if (isResult) {
4658 resultOut.setPreparedResultUpdateProperties(parameterValues);
4659 } else {
4660 resultOut.setPreparedExecuteProperties(parameterValues, maxRows,
4661 fetchSize, rsProperties, queryTimeout);
4662 }
4663
4664 try {
4665 performPreExecute();
4666
4667 resultIn = session.execute(resultOut);
4668 } catch (HsqlException e) {
4669 throw JDBCUtil.sqlException(e);
4670 } finally {
4671 performPostExecute();
4672 }
4673
4674 if (resultIn.mode == ResultConstants.ERROR) {
4675 throw JDBCUtil.sqlException(resultIn);
4676 }
4677
4678 if (resultIn.isData()) {
4679 currentResultSet = new JDBCResultSet(connection, this, resultIn,
4680 resultIn.metaData);
4681 } else if (statementRetType == StatementTypes.RETURN_RESULT) {
4682 getMoreResults();
4683 }
4684 }
4685
4686 boolean isAnyParameterSet() {
4687
4688 for (int i = 0; i < parameterValues.length; i++) {
4689 if (parameterSet[i] != null) {
4690 return true;
4691 }
4692 }
4693
4694 return false;
4695 }
4696
4697 /**
4698 * processes chained warnings and any generated columns result set
4699 */
4700 void performPostExecute() throws SQLException {
4701 super.performPostExecute();
4702 }
4703
4704 /** The parameter values for the next non-batch execution. */
4705 protected Object[] parameterValues;
4706
4707 /** Flags for bound variables. */
4708 protected Boolean[] parameterSet;
4709
4710 /** The SQL types of the parameters. */
4711 protected Type[] parameterTypes;
4712
4713 /** The (IN, IN OUT, or OUT) modes of parameters */
4714 protected byte[] parameterModes;
4715
4716 /** Lengths for streams. */
4717 protected long[] streamLengths;
4718
4719 /** Has one or more CLOB / BLOB type parameters. */
4720 protected boolean hasLOBs;
4721
4722 /** Is in batch mode. */
4723 protected boolean isBatch;
4724
4725 /** Description of result set metadata. */
4726 protected ResultMetaData resultMetaData;
4727
4728 /** Description of parameter metadata. */
4729 protected ResultMetaData parameterMetaData;
4730
4731 /** This object's one and one ResultSetMetaData object. */
4732 protected JDBCResultSetMetaData resultSetMetaData;
4733
4734 // NOTE: pmd is declared as Object to avoid yet another #ifdef.
4735
4736 /** This object's one and only ParameterMetaData object. */
4737 protected Object pmd;
4738
4739 /** The SQL character sequence that this object represents. */
4740 protected String sql;
4741
4742 /** ID of the statement. */
4743 protected long statementID;
4744
4745 /** Statement type - whether it generates a row update count or a result set. */
4746 protected int statementRetType;
4747
4748 /** Is part of a Result. */
4749 protected final boolean isResult;
4750
4751 /** The session attribute of the connection */
4752 protected SessionInterface session;
4753 }
4754