1 /***
2 * WrappedPreparedStatement.java
3 *
4 * This file is part of the creme library.
5 * The creme library intends to ease the development effort of large
6 * applications by providing easy to use support classes.
7 *
8 * Copyright (C) 2002 Denis Bregeon
9 *
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * contact information: dbregeon@sourceforge.net
26 */
27 package org.jcreme.sql;
28
29 import java.io.InputStream;
30 import java.io.Reader;
31 import java.math.BigDecimal;
32 import java.net.URL;
33 import java.sql.Array;
34 import java.sql.Blob;
35 import java.sql.Clob;
36 import java.sql.Date;
37 import java.sql.ParameterMetaData;
38 import java.sql.PreparedStatement;
39 import java.sql.Ref;
40 import java.sql.ResultSet;
41 import java.sql.ResultSetMetaData;
42 import java.sql.SQLException;
43 import java.sql.Statement;
44 import java.sql.Time;
45 import java.sql.Timestamp;
46 import java.util.Calendar;
47
48 /***
49 * This class enables to wrap an actual statement to provide a few extra
50 * services: tracing of the queries, handling of some exceptions (rollback, loss
51 * of connection). The ResultSets provided by this class are wrapped around the
52 * actual ResultSet.
53 *
54 * @author $Author: dbregeon $
55 * @version $Revision: 1.1 $
56 */
57 public class WrappedPreparedStatement extends WrappedStatement implements
58 PreparedStatement {
59 /***
60 * This array records the parameters that have currently been set in the
61 * PreparedStatement.
62 */
63 private Object[] currentParams = null;
64
65 /***
66 * Enables to wrap a PreparedStatement.
67 *
68 * @param preparedStatement
69 * the statement to wrap.
70 * @param sql
71 * the query associated to the PreparedStatement.
72 * @throws SQLException
73 * if the preparedStatement is null.
74 */
75 public WrappedPreparedStatement(PreparedStatement preparedStatement,
76 String sql) throws SQLException {
77 super(preparedStatement);
78 if (preparedStatement == null) {
79 throw new SQLException("Null Prepared Statement.");
80 }
81 setBaseQuery(sql);
82 }
83
84 /***
85 * This method enables to set the base query of the statement.
86 *
87 * @param sql
88 * the sql query underlying the statement.
89 * @throws SQLException
90 * if the query is null.
91 */
92 protected void setBaseQuery(String sql) throws SQLException {
93 super.setBaseQuery(sql);
94 int j = 0;
95 for (int i = sql.indexOf('?', 0); i >= 0; i = sql.indexOf('?', i)) {
96 j++;
97 i++;
98 }
99 this.currentParams = new Object[j];
100 }
101
102 /***
103 * This method enables to substitute the parameters set in the statement in
104 * the baseQuery. They replace the '?'.
105 *
106 * @return the current query.
107 */
108 protected String buildActualQuery() {
109 String actualQuery = new String(super.baseQuery);
110 int i = actualQuery.indexOf('?');
111 String paramString;
112 for (int j = 0; j < this.currentParams.length; j++) {
113 if (this.currentParams[j] != null) {
114 paramString = this.currentParams[j].toString();
115 } else {
116 paramString = "null";
117 }
118 String beforeParam = actualQuery.substring(0, i);
119 String afterParam = actualQuery.substring(i + 1);
120 actualQuery = beforeParam + "'" + paramString + "'" + afterParam;
121 i = actualQuery.indexOf('?');
122 }
123 return actualQuery;
124 }
125
126 /***
127 * This method enables to append a message to the original exception's
128 * message.
129 *
130 * @param e
131 * the original exception.
132 * @return an exception with the appended message.
133 */
134 protected SQLException generateException(SQLException e) {
135 return super.generateException(buildActualQuery(), e);
136 }
137
138 /***
139 * Executes the SQL query in this <code>PreparedStatement</code> object
140 * and returns the <code>ResultSet</code> object generated by the query.
141 *
142 * @return a <code>ResultSet</code> object that contains the data produced
143 * by the query; never <code>null</code>
144 * @exception SQLException
145 * if a database access error occurs or the SQL statement
146 * does not return a <code>ResultSet</code> object
147 */
148 public ResultSet executeQuery() throws SQLException {
149 try {
150 return new WrappedResultSet(
151 ((PreparedStatement) super.realStatement).executeQuery(),
152 this, buildActualQuery());
153 } catch (SQLException e) {
154 CremeAction redo = null;
155 try {
156 redo = new CremeAction(getClass().getMethod("executeQuery",
157 new Class[0]));
158 redo.setSubject(this);
159 } catch (NoSuchMethodException ex) {
160 ex.printStackTrace();
161 } catch (IllegalArgumentException ex) {
162 ex.printStackTrace();
163 }
164 manageException(e, redo);
165 if (redo != null && redo.isSuccessfull()) {
166 return (ResultSet) redo.getResult();
167 }
168 throw generateException(e);
169 }
170 }
171
172 /***
173 * Executes the SQL statement in this <code>PreparedStatement</code>
174 * object, which must be an SQL <code>INSERT</code>,<code>UPDATE</code>
175 * or <code>DELETE</code> statement; or an SQL statement that returns
176 * nothing, such as a DDL statement.
177 *
178 * @return either (1) the row count for <code>INSERT</code>,
179 * <code>UPDATE</code>, or <code>DELETE</code> statements or
180 * (2) 0 for SQL statements that return nothing
181 * @exception SQLException
182 * if a database access error occurs or the SQL statement
183 * returns a <code>ResultSet</code> object
184 */
185 public int executeUpdate() throws SQLException {
186 try {
187 return ((PreparedStatement) super.realStatement).executeUpdate();
188 } catch (SQLException e) {
189 CremeAction redo = null;
190 try {
191 redo = new CremeAction(getClass().getMethod("executeUpdate",
192 new Class[0]));
193 redo.setSubject(this);
194 } catch (NoSuchMethodException ex) {
195 ex.printStackTrace();
196 } catch (IllegalArgumentException ex) {
197 ex.printStackTrace();
198 }
199 manageException(e, redo);
200 if (redo != null && redo.isSuccessfull()) {
201 return ((Integer) redo.getResult()).intValue();
202 }
203 throw generateException(e);
204 }
205 }
206
207 /***
208 * Sets the designated parameter to SQL <code>NULL</code>.
209 *
210 * <P>
211 * <B>Note: </B> You must specify the parameter's SQL type.
212 *
213 * @param parameterIndex
214 * the first parameter is 1, the second is 2, ...
215 * @param sqlType
216 * the SQL type code defined in <code>java.sql.Types</code>
217 * @exception SQLException
218 * if a database access error occurs
219 */
220 public void setNull(int parameterIndex, int sqlType) throws SQLException {
221 try {
222 ((PreparedStatement) this.realStatement).setNull(parameterIndex,
223 sqlType);
224 if (parameterIndex <= this.currentParams.length) {
225 this.currentParams[parameterIndex - 1] = null;
226 }
227 } catch (SQLException e) {
228 manageException(e);
229 throw generateException(e);
230 }
231 }
232
233 /***
234 * Sets the designated parameter to the given Java <code>boolean</code>
235 * value. The driver converts this to an SQL <code>BIT</code> value when
236 * it sends it to the database.
237 *
238 * @param parameterIndex
239 * the first parameter is 1, the second is 2, ...
240 * @param x
241 * the parameter value
242 * @exception SQLException
243 * if a database access error occurs
244 */
245 public void setBoolean(int parameterIndex, boolean x) throws SQLException {
246 try {
247 ((PreparedStatement) this.realStatement).setBoolean(parameterIndex,
248 x);
249 if (parameterIndex <= this.currentParams.length)
250 this.currentParams[parameterIndex - 1] = new Boolean(x);
251 } catch (SQLException sqlexception) {
252 manageException(sqlexception);
253 throw generateException(sqlexception);
254 }
255 }
256
257 /***
258 * Sets the designated parameter to the given Java <code>byte</code>
259 * value. The driver converts this to an SQL <code>TINYINT</code> value
260 * when it sends it to the database.
261 *
262 * @param parameterIndex
263 * the first parameter is 1, the second is 2, ...
264 * @param x
265 * the parameter value
266 * @exception SQLException
267 * if a database access error occurs
268 */
269 public void setByte(int parameterIndex, byte x) throws SQLException {
270 try {
271 ((PreparedStatement) this.realStatement).setByte(parameterIndex, x);
272 if (parameterIndex <= this.currentParams.length) {
273 this.currentParams[parameterIndex - 1] = new Integer(x);
274 }
275 } catch (SQLException e) {
276 manageException(e);
277 throw generateException(e);
278 }
279 }
280
281 /***
282 * Sets the designated parameter to the given Java <code>short</code>
283 * value. The driver converts this to an SQL <code>SMALLINT</code> value
284 * when it sends it to the database.
285 *
286 * @param parameterIndex
287 * the first parameter is 1, the second is 2, ...
288 * @param x
289 * the parameter value
290 * @exception SQLException
291 * if a database access error occurs
292 */
293 public void setShort(int parameterIndex, short x) throws SQLException {
294 try {
295 ((PreparedStatement) this.realStatement)
296 .setShort(parameterIndex, x);
297 if (parameterIndex <= this.currentParams.length) {
298 this.currentParams[parameterIndex - 1] = new Integer(x);
299 }
300 } catch (SQLException e) {
301 manageException(e);
302 throw generateException(e);
303 }
304 }
305
306 /***
307 * Sets the designated parameter to the given Java <code>int</code> value.
308 * The driver converts this to an SQL <code>INTEGER</code> value when it
309 * sends it to the database.
310 *
311 * @param parameterIndex
312 * the first parameter is 1, the second is 2, ...
313 * @param x
314 * the parameter value
315 * @exception SQLException
316 * if a database access error occurs
317 */
318 public void setInt(int parameterIndex, int x) throws SQLException {
319 try {
320 ((PreparedStatement) this.realStatement).setInt(parameterIndex, x);
321 if (parameterIndex <= this.currentParams.length) {
322 this.currentParams[parameterIndex - 1] = new Integer(x);
323 }
324 } catch (SQLException e) {
325 manageException(e);
326 throw generateException(e);
327 }
328 }
329
330 /***
331 * Sets the designated parameter to the given Java <code>long</code>
332 * value. The driver converts this to an SQL <code>BIGINT</code> value
333 * when it sends it to the database.
334 *
335 * @param parameterIndex
336 * the first parameter is 1, the second is 2, ...
337 * @param x
338 * the parameter value
339 * @exception SQLException
340 * if a database access error occurs
341 */
342 public void setLong(int parameterIndex, long x) throws SQLException {
343 try {
344 ((PreparedStatement) this.realStatement).setLong(parameterIndex, x);
345 if (parameterIndex <= this.currentParams.length) {
346 this.currentParams[parameterIndex - 1] = new Long(x);
347 }
348 } catch (SQLException e) {
349 manageException(e);
350 throw generateException(e);
351 }
352 }
353
354 /***
355 * Sets the designated parameter to the given Java <code>float</code>
356 * value. The driver converts this to an SQL <code>FLOAT</code> value when
357 * it sends it to the database.
358 *
359 * @param parameterIndex
360 * the first parameter is 1, the second is 2, ...
361 * @param x
362 * the parameter value
363 * @exception SQLException
364 * if a database access error occurs
365 */
366 public void setFloat(int parameterIndex, float x) throws SQLException {
367 try {
368 ((PreparedStatement) this.realStatement)
369 .setFloat(parameterIndex, x);
370 if (parameterIndex <= this.currentParams.length) {
371 this.currentParams[parameterIndex - 1] = new Double(x);
372 }
373 } catch (SQLException e) {
374 manageException(e);
375 throw generateException(e);
376 }
377 }
378
379 /***
380 * Sets the designated parameter to the given Java <code>double</code>
381 * value. The driver converts this to an SQL <code>DOUBLE</code> value
382 * when it sends it to the database.
383 *
384 * @param parameterIndex
385 * the first parameter is 1, the second is 2, ...
386 * @param x
387 * the parameter value
388 * @exception SQLException
389 * if a database access error occurs
390 */
391 public void setDouble(int parameterIndex, double x) throws SQLException {
392 try {
393 ((PreparedStatement) this.realStatement).setDouble(parameterIndex,
394 x);
395 if (parameterIndex <= this.currentParams.length) {
396 this.currentParams[parameterIndex - 1] = new Double(x);
397 }
398 } catch (SQLException e) {
399 manageException(e);
400 throw generateException(e);
401 }
402 }
403
404 /***
405 * Sets the designated parameter to the given
406 * <code>java.math.BigDecimal</code> value. The driver converts this to an
407 * SQL <code>NUMERIC</code> value when it sends it to the database.
408 *
409 * @param parameterIndex
410 * the first parameter is 1, the second is 2, ...
411 * @param x
412 * the parameter value
413 * @exception SQLException
414 * if a database access error occurs
415 */
416 public void setBigDecimal(int parameterIndex, BigDecimal x)
417 throws SQLException {
418 try {
419 ((PreparedStatement) this.realStatement).setBigDecimal(
420 parameterIndex, x);
421 if (parameterIndex <= this.currentParams.length) {
422 this.currentParams[parameterIndex - 1] = x;
423 }
424 } catch (SQLException e) {
425 manageException(e);
426 throw generateException(e);
427 }
428 }
429
430 /***
431 * Sets the designated parameter to the given Java <code>String</code>
432 * value. The driver converts this to an SQL <code>VARCHAR</code> or
433 * <code>LONGVARCHAR</code> value (depending on the argument's size
434 * relative to the driver's limits on <code>VARCHAR</code> values) when it
435 * sends it to the database.
436 *
437 * @param parameterIndex
438 * the first parameter is 1, the second is 2, ...
439 * @param x
440 * the parameter value
441 * @exception SQLException
442 * if a database access error occurs
443 */
444 public void setString(int parameterIndex, String x) throws SQLException {
445 try {
446 ((PreparedStatement) this.realStatement).setString(parameterIndex,
447 x);
448 if (parameterIndex <= this.currentParams.length) {
449 if (x != null) {
450 this.currentParams[parameterIndex - 1] = new String(x);
451 } else {
452 this.currentParams[parameterIndex - 1] = null;
453 }
454 }
455 } catch (SQLException e) {
456 manageException(e);
457 throw generateException(e);
458 }
459 }
460
461 /***
462 * Sets the designated parameter to the given Java array of bytes. The
463 * driver converts this to an SQL <code>VARBINARY</code> or
464 * <code>LONGVARBINARY</code> (depending on the argument's size relative
465 * to the driver's limits on <code>VARBINARY</code> values) when it sends
466 * it to the database.
467 *
468 * @param parameterIndex
469 * the first parameter is 1, the second is 2, ...
470 * @param x
471 * the parameter value
472 * @exception SQLException
473 * if a database access error occurs
474 */
475 public void setBytes(int parameterIndex, byte[] x) throws SQLException {
476 try {
477 ((PreparedStatement) this.realStatement)
478 .setBytes(parameterIndex, x);
479 if (parameterIndex <= this.currentParams.length) {
480 if (x != null) {
481 this.currentParams[parameterIndex - 1] = x;
482 } else {
483 this.currentParams[parameterIndex - 1] = null;
484 }
485 }
486 } catch (SQLException e) {
487 manageException(e);
488 throw generateException(e);
489 }
490 }
491
492 /***
493 * Sets the designated parameter to the given <code>java.sql.Date</code>
494 * value. The driver converts this to an SQL <code>DATE</code> value when
495 * it sends it to the database.
496 *
497 * @param parameterIndex
498 * the first parameter is 1, the second is 2, ...
499 * @param x
500 * the parameter value
501 * @exception SQLException
502 * if a database access error occurs
503 */
504 public void setDate(int parameterIndex, Date x) throws SQLException {
505 try {
506 ((PreparedStatement) this.realStatement).setDate(parameterIndex, x);
507 if (parameterIndex <= this.currentParams.length) {
508 if (x != null) {
509 this.currentParams[parameterIndex - 1] = x.clone();
510 } else {
511 this.currentParams[parameterIndex - 1] = null;
512 }
513 }
514 } catch (SQLException e) {
515 manageException(e);
516 throw generateException(e);
517 }
518 }
519
520 /***
521 * Sets the designated parameter to the given <code>java.sql.Time</code>
522 * value. The driver converts this to an SQL <code>TIME</code> value when
523 * it sends it to the database.
524 *
525 * @param parameterIndex
526 * the first parameter is 1, the second is 2, ...
527 * @param x
528 * the parameter value
529 * @exception SQLException
530 * if a database access error occurs
531 */
532 public void setTime(int parameterIndex, Time x) throws SQLException {
533 try {
534 ((PreparedStatement) this.realStatement).setTime(parameterIndex, x);
535 if (parameterIndex <= this.currentParams.length) {
536 if (x != null) {
537 this.currentParams[parameterIndex - 1] = x.clone();
538 } else {
539 this.currentParams[parameterIndex - 1] = null;
540 }
541 }
542 } catch (SQLException e) {
543 manageException(e);
544 throw generateException(e);
545 }
546 }
547
548 /***
549 * Sets the designated parameter to the given
550 * <code>java.sql.Timestamp</code> value. The driver converts this to an
551 * SQL <code>TIMESTAMP</code> value when it sends it to the database.
552 *
553 * @param parameterIndex
554 * the first parameter is 1, the second is 2, ...
555 * @param x
556 * the parameter value
557 * @exception SQLException
558 * if a database access error occurs
559 */
560 public void setTimestamp(int parameterIndex, Timestamp x)
561 throws SQLException {
562 try {
563 ((PreparedStatement) this.realStatement).setTimestamp(
564 parameterIndex, x);
565 if (parameterIndex <= this.currentParams.length) {
566 if (x != null) {
567 this.currentParams[parameterIndex - 1] = x.clone();
568 } else {
569 this.currentParams[parameterIndex - 1] = null;
570 }
571 }
572 } catch (SQLException e) {
573 manageException(e);
574 throw generateException(e);
575 }
576 }
577
578 /***
579 * Sets the designated parameter to the given input stream, which will have
580 * the specified number of bytes. When a very large ASCII value is input to
581 * a <code>LONGVARCHAR</code> parameter, it may be more practical to send
582 * it via a <code>java.io.InputStream</code>. Data will be read from the
583 * stream as needed until end-of-file is reached. The JDBC driver will do
584 * any necessary conversion from ASCII to the database char format.
585 *
586 * <P>
587 * <B>Note: </B> This stream object can either be a standard Java stream
588 * object or your own subclass that implements the standard interface.
589 *
590 * @param parameterIndex
591 * the first parameter is 1, the second is 2, ...
592 * @param x
593 * the Java input stream that contains the ASCII parameter value
594 * @param length
595 * the number of bytes in the stream
596 * @exception SQLException
597 * if a database access error occurs
598 */
599 public void setAsciiStream(int parameterIndex, InputStream x, int length)
600 throws SQLException {
601 try {
602 ((PreparedStatement) this.realStatement).setAsciiStream(
603 parameterIndex, x, length);
604 if (parameterIndex <= this.currentParams.length) {
605 this.currentParams[parameterIndex - 1] = "From Ascii Stream";
606 }
607 } catch (SQLException e) {
608 manageException(e);
609 throw generateException(e);
610 }
611 }
612
613 /***
614 * Sets the designated parameter to the given input stream, which will have
615 * the specified number of bytes. A Unicode character has two bytes, with
616 * the first byte being the high byte, and the second being the low byte.
617 *
618 * When a very large Unicode value is input to a <code>LONGVARCHAR</code>
619 * parameter, it may be more practical to send it via a
620 * <code>java.io.InputStream</code> object. The data will be read from the
621 * stream as needed until end-of-file is reached. The JDBC driver will do
622 * any necessary conversion from Unicode to the database char format.
623 *
624 * <P>
625 * <B>Note: </B> This stream object can either be a standard Java stream
626 * object or your own subclass that implements the standard interface.
627 *
628 * @param parameterIndex
629 * the first parameter is 1, the second is 2, ...
630 * @param x
631 * a <code>java.io.InputStream</code> object that contains the
632 * Unicode parameter value as two-byte Unicode characters
633 * @param length
634 * the number of bytes in the stream
635 * @exception SQLException
636 * if a database access error occurs
637 * @deprecated
638 */
639 public void setUnicodeStream(int parameterIndex, InputStream x, int length)
640 throws SQLException {
641 try {
642 ((PreparedStatement) this.realStatement).setUnicodeStream(
643 parameterIndex, x, length);
644 if (parameterIndex <= this.currentParams.length) {
645 this.currentParams[parameterIndex - 1] = "From Unicode Stream";
646 }
647 } catch (SQLException e) {
648 manageException(e);
649 throw generateException(e);
650 }
651 }
652
653 /***
654 * Sets the designated parameter to the given input stream, which will have
655 * the specified number of bytes. When a very large binary value is input to
656 * a <code>LONGVARBINARY</code> parameter, it may be more practical to
657 * send it via a <code>java.io.InputStream</code> object. The data will be
658 * read from the stream as needed until end-of-file is reached.
659 *
660 * <P>
661 * <B>Note: </B> This stream object can either be a standard Java stream
662 * object or your own subclass that implements the standard interface.
663 *
664 * @param parameterIndex
665 * the first parameter is 1, the second is 2, ...
666 * @param x
667 * the java input stream which contains the binary parameter
668 * value
669 * @param length
670 * the number of bytes in the stream
671 * @exception SQLException
672 * if a database access error occurs
673 */
674 public void setBinaryStream(int parameterIndex, InputStream x, int length)
675 throws SQLException {
676 try {
677 ((PreparedStatement) this.realStatement).setBinaryStream(
678 parameterIndex, x, length);
679 if (parameterIndex <= this.currentParams.length) {
680 this.currentParams[parameterIndex - 1] = "From Binary Stream";
681 }
682 } catch (SQLException e) {
683 manageException(e);
684 throw generateException(e);
685 }
686 }
687
688 /***
689 * Clears the current parameter values immediately.
690 * <P>
691 * In general, parameter values remain in force for repeated use of a
692 * statement. Setting a parameter value automatically clears its previous
693 * value. However, in some cases it is useful to immediately release the
694 * resources used by the current parameter values; this can be done by
695 * calling the method <code>clearParameters</code>.
696 *
697 * @exception SQLException
698 * if a database access error occurs
699 */
700 public void clearParameters() throws SQLException {
701 try {
702 ((PreparedStatement) this.realStatement).clearParameters();
703 for (int i = 0; i < this.currentParams.length; i++) {
704 this.currentParams[i] = null;
705 }
706 } catch (SQLException e) {
707 manageException(e);
708 throw generateException(e);
709 }
710 }
711
712 /***
713 * <p>
714 * Sets the value of the designated parameter with the given object. The
715 * second argument must be an object type; for integral values, the
716 * <code>java.lang</code> equivalent objects should be used.
717 *
718 * <p>
719 * The given Java object will be converted to the given targetSqlType before
720 * being sent to the database.
721 *
722 * If the object has a custom mapping (is of a class implementing the
723 * interface <code>SQLData</code>), the JDBC driver should call the
724 * method <code>SQLData.writeSQL</code> to write it to the SQL data
725 * stream. If, on the other hand, the object is of a class implementing
726 * <code>Ref</code>,<code>Blob</code>,<code>Clob</code>,
727 * <code>Struct</code>, or <code>Array</code>, the driver should pass
728 * it to the database as a value of the corresponding SQL type.
729 *
730 * <p>
731 * Note that this method may be used to pass database-specific abstract data
732 * types.
733 *
734 * @param parameterIndex
735 * the first parameter is 1, the second is 2, ...
736 * @param x
737 * the object containing the input parameter value
738 * @param targetSqlType
739 * the SQL type (as defined in java.sql.Types) to be sent to the
740 * database. The scale argument may further qualify this type.
741 * @param scale
742 * for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
743 * this is the number of digits after the decimal point. For all
744 * other types, this value will be ignored.
745 * @exception SQLException
746 * if a database access error occurs
747 */
748 public void setObject(int parameterIndex, Object x, int targetSqlType,
749 int scale) throws SQLException {
750 try {
751 ((PreparedStatement) this.realStatement).setObject(parameterIndex,
752 x, targetSqlType, scale);
753 if (parameterIndex <= this.currentParams.length) {
754 this.currentParams[parameterIndex - 1] = x;
755 }
756 } catch (SQLException e) {
757 manageException(e);
758 throw generateException(e);
759 }
760 }
761
762 /***
763 * Sets the value of the designated parameter with the given object. This
764 * method is like the method <code>setObject</code> above, except that it
765 * assumes a scale of zero.
766 *
767 * @param parameterIndex
768 * the first parameter is 1, the second is 2, ...
769 * @param x
770 * the object containing the input parameter value
771 * @param targetSqlType
772 * the SQL type (as defined in java.sql.Types) to be sent to the
773 * database
774 * @exception SQLException
775 * if a database access error occurs
776 */
777 public void setObject(int parameterIndex, Object x, int targetSqlType)
778 throws SQLException {
779 try {
780 ((PreparedStatement) this.realStatement).setObject(targetSqlType,
781 x, targetSqlType);
782 if (parameterIndex <= this.currentParams.length) {
783 this.currentParams[parameterIndex - 1] = x;
784 }
785 } catch (SQLException e) {
786 manageException(e);
787 throw generateException(e);
788 }
789 }
790
791 /***
792 * <p>
793 * Sets the value of the designated parameter using the given object. The
794 * second parameter must be of type <code>Object</code>; therefore, the
795 * <code>java.lang</code> equivalent objects should be used for built-in
796 * types.
797 *
798 * <p>
799 * The JDBC specification specifies a standard mapping from Java
800 * <code>Object</code> types to SQL types. The given argument will be
801 * converted to the corresponding SQL type before being sent to the
802 * database.
803 *
804 * <p>
805 * Note that this method may be used to pass datatabase- specific abstract
806 * data types, by using a driver-specific Java type.
807 *
808 * If the object is of a class implementing the interface
809 * <code>SQLData</code>, the JDBC driver should call the method
810 * <code>SQLData.writeSQL</code> to write it to the SQL data stream. If,
811 * on the other hand, the object is of a class implementing <code>Ref</code>,
812 * <code>Blob</code>,<code>Clob</code>,<code>Struct</code>, or
813 * <code>Array</code>, the driver should pass it to the database as a
814 * value of the corresponding SQL type.
815 * <P>
816 * This method throws an exception if there is an ambiguity, for example, if
817 * the object is of a class implementing more than one of the interfaces
818 * named above.
819 *
820 * @param parameterIndex
821 * the first parameter is 1, the second is 2, ...
822 * @param x
823 * the object containing the input parameter value
824 * @exception SQLException
825 * if a database access error occurs or the type of the given
826 * object is ambiguous
827 */
828 public void setObject(int parameterIndex, Object x) throws SQLException {
829 try {
830 ((PreparedStatement) this.realStatement).setObject(parameterIndex,
831 x);
832 if (parameterIndex <= this.currentParams.length) {
833 this.currentParams[parameterIndex - 1] = x;
834 }
835 } catch (SQLException e) {
836 manageException(e);
837 throw generateException(e);
838 }
839 }
840
841 /***
842 * Executes the SQL statement in this <code>PreparedStatement</code>
843 * object, which may be any kind of SQL statement. Some prepared statements
844 * return multiple results; the <code>execute</code> method handles these
845 * complex statements as well as the simpler form of statements handled by
846 * the methods <code>executeQuery</code> and <code>executeUpdate</code>.
847 * <P>
848 * The <code>execute</code> method returns a <code>boolean</code> to
849 * indicate the form of the first result. You must call either the method
850 * <code>getResultSet</code> or <code>getUpdateCount</code> to retrieve
851 * the result; you must call <code>getMoreResults</code> to move to any
852 * subsequent result(s).
853 *
854 * @return <code>true</code> if the first result is a
855 * <code>ResultSet</code> object; <code>false</code> if the
856 * first result is an update count or there is no result
857 * @exception SQLException
858 * if a database access error occurs or an argument is
859 * supplied to this method
860 */
861 public boolean execute() throws SQLException {
862 try {
863 return ((PreparedStatement) this.realStatement).execute();
864 } catch (SQLException e) {
865 CremeAction redo = null;
866 try {
867 redo = new CremeAction(getClass().getMethod("execute",
868 new Class[0]));
869 redo.setSubject(this);
870 } catch (NoSuchMethodException ex) {
871 ex.printStackTrace();
872 } catch (IllegalArgumentException ex) {
873 ex.printStackTrace();
874 }
875 manageException(e, redo);
876 if ((redo != null) && (redo.isSuccessfull())) {
877 return ((Boolean) redo.getResult()).booleanValue();
878 }
879 throw generateException(e);
880 }
881 }
882
883 /***
884 * Adds a set of parameters to this <code>PreparedStatement</code>
885 * object's batch of commands.
886 *
887 * @exception SQLException
888 * if a database access error occurs
889 * @see Statement#addBatch
890 * @since 1.2
891 */
892 public void addBatch() throws SQLException {
893 try {
894 ((PreparedStatement) this.realStatement).addBatch();
895 this.batchRequests.add(this.currentParams);
896 this.currentParams = new Object[this.currentParams.length];
897 } catch (SQLException e) {
898 throw generateException(e);
899 }
900 }
901
902 /***
903 * This method enables to access the batched queries.
904 *
905 * @param index
906 * the index of the batch request.
907 * @return a string that represents the batch request at the given index.
908 */
909 protected String getBatchRequestAt(int index) {
910 String result = null;
911 Object obj = this.batchRequests.elementAt(index);
912 if (obj instanceof String) {
913 result = (String) obj;
914 } else {
915 Object[] params = this.currentParams;
916 this.currentParams = (Object[]) obj;
917 result = buildActualQuery();
918 this.currentParams = params;
919 }
920 return result;
921 }
922
923 /***
924 * Sets the designated parameter to the given <code>Reader</code> object,
925 * which is the given number of characters long. When a very large UNICODE
926 * value is input to a <code>LONGVARCHAR</code> parameter, it may be more
927 * practical to send it via a <code>java.io.Reader</code> object. The data
928 * will be read from the stream as needed until end-of-file is reached. The
929 * JDBC driver will do any necessary conversion from UNICODE to the database
930 * char format.
931 *
932 * <P>
933 * <B>Note: </B> This stream object can either be a standard Java stream
934 * object or your own subclass that implements the standard interface.
935 *
936 * @param parameterIndex
937 * the first parameter is 1, the second is 2, ...
938 * @param reader
939 * the <code>java.io.Reader</code> object that contains the
940 * Unicode data
941 * @param length
942 * the number of characters in the stream
943 * @exception SQLException
944 * if a database access error occurs
945 * @since 1.2
946 */
947 public void setCharacterStream(int parameterIndex, Reader reader, int length)
948 throws SQLException {
949 try {
950 ((PreparedStatement) this.realStatement).setCharacterStream(
951 parameterIndex, reader, length);
952 if (parameterIndex <= this.currentParams.length) {
953 this.currentParams[parameterIndex - 1] = "From Character Stream";
954 }
955 } catch (SQLException e) {
956 manageException(e);
957 throw generateException(e);
958 }
959 }
960
961 /***
962 * Sets the designated parameter to the given
963 * <code>REF(<structured-type>)</code> value. The driver converts
964 * this to an SQL <code>REF</code> value when it sends it to the database.
965 *
966 * @param i
967 * the first parameter is 1, the second is 2, ...
968 * @param x
969 * an SQL <code>REF</code> value
970 * @exception SQLException
971 * if a database access error occurs
972 * @since 1.2
973 */
974 public void setRef(int i, Ref x) throws SQLException {
975 try {
976 ((PreparedStatement) this.realStatement).setRef(i, x);
977 if (i <= this.currentParams.length) {
978 this.currentParams[i - 1] = x;
979 }
980 } catch (SQLException e) {
981 manageException(e);
982 throw generateException(e);
983 }
984 }
985
986 /***
987 * Sets the designated parameter to the given <code>Blob</code> object.
988 * The driver converts this to an SQL <code>BLOB</code> value when it
989 * sends it to the database.
990 *
991 * @param i
992 * the first parameter is 1, the second is 2, ...
993 * @param x
994 * a <code>Blob</code> object that maps an SQL
995 * <code>BLOB</code> value
996 * @exception SQLException
997 * if a database access error occurs
998 * @since 1.2
999 */
1000 public void setBlob(int i, Blob x) throws SQLException {
1001 try {
1002 ((PreparedStatement) this.realStatement).setBlob(i, x);
1003 if (i <= this.currentParams.length) {
1004 this.currentParams[i - 1] = x;
1005 }
1006 } catch (SQLException e) {
1007 manageException(e);
1008 throw generateException(e);
1009 }
1010 }
1011
1012 /***
1013 * Sets the designated parameter to the given <code>Clob</code> object.
1014 * The driver converts this to an SQL <code>CLOB</code> value when it
1015 * sends it to the database.
1016 *
1017 * @param i
1018 * the first parameter is 1, the second is 2, ...
1019 * @param x
1020 * a <code>Clob</code> object that maps an SQL
1021 * <code>CLOB</code> value
1022 * @exception SQLException
1023 * if a database access error occurs
1024 * @since 1.2
1025 */
1026 public void setClob(int i, Clob x) throws SQLException {
1027 try {
1028 ((PreparedStatement) this.realStatement).setClob(i, x);
1029 if (i <= this.currentParams.length) {
1030 this.currentParams[i - 1] = x;
1031 }
1032 } catch (SQLException e) {
1033 manageException(e);
1034 throw generateException(e);
1035 }
1036 }
1037
1038 /***
1039 * Sets the designated parameter to the given <code>Array</code> object.
1040 * The driver converts this to an SQL <code>ARRAY</code> value when it
1041 * sends it to the database.
1042 *
1043 * @param i
1044 * the first parameter is 1, the second is 2, ...
1045 * @param x
1046 * an <code>Array</code> object that maps an SQL
1047 * <code>ARRAY</code> value
1048 * @exception SQLException
1049 * if a database access error occurs
1050 * @since 1.2
1051 */
1052 public void setArray(int i, Array x) throws SQLException {
1053 try {
1054 ((PreparedStatement) this.realStatement).setArray(i, x);
1055 if (i <= this.currentParams.length) {
1056 this.currentParams[i - 1] = x;
1057 }
1058 } catch (SQLException e) {
1059 manageException(e);
1060 throw generateException(e);
1061 }
1062 }
1063
1064 /***
1065 * Retrieves a <code>ResultSetMetaData</code> object that contains
1066 * information about the columns of the <code>ResultSet</code> object that
1067 * will be returned when this <code>PreparedStatement</code> object is
1068 * executed.
1069 * <P>
1070 * Because a <code>PreparedStatement</code> object is precompiled, it is
1071 * possible to know about the <code>ResultSet</code> object that it will
1072 * return without having to execute it. Consequently, it is possible to
1073 * invoke the method <code>getMetaData</code> on a
1074 * <code>PreparedStatement</code> object rather than waiting to execute it
1075 * and then invoking the <code>ResultSet.getMetaData</code> method on the
1076 * <code>ResultSet</code> object that is returned.
1077 * <P>
1078 * <B>NOTE: </B> Using this method may be expensive for some drivers due to
1079 * the lack of underlying DBMS support.
1080 *
1081 * @return the description of a <code>ResultSet</code> object's columns or
1082 * <code>null</code> if the driver cannot return a
1083 * <code>ResultSetMetaData</code> object
1084 * @exception SQLException
1085 * if a database access error occurs
1086 * @since 1.2
1087 */
1088 public ResultSetMetaData getMetaData() throws SQLException {
1089 try {
1090 return ((PreparedStatement) this.realStatement).getMetaData();
1091 } catch (SQLException e) {
1092 manageException(e);
1093 throw generateException(e);
1094 }
1095 }
1096
1097 /***
1098 * Sets the designated parameter to the given <code>java.sql.Date</code>
1099 * value, using the given <code>Calendar</code> object. The driver uses
1100 * the <code>Calendar</code> object to construct an SQL <code>DATE</code>
1101 * value, which the driver then sends to the database. With a a
1102 * <code>Calendar</code> object, the driver can calculate the date taking
1103 * into account a custom timezone. If no <code>Calendar</code> object is
1104 * specified, the driver uses the default timezone, which is that of the
1105 * virtual machine running the application.
1106 *
1107 * @param parameterIndex
1108 * the first parameter is 1, the second is 2, ...
1109 * @param x
1110 * the parameter value
1111 * @param cal
1112 * the <code>Calendar</code> object the driver will use to
1113 * construct the date
1114 * @exception SQLException
1115 * if a database access error occurs
1116 * @since 1.2
1117 */
1118 public void setDate(int parameterIndex, Date x, Calendar cal)
1119 throws SQLException {
1120 try {
1121 ((PreparedStatement) this.realStatement).setDate(parameterIndex, x,
1122 cal);
1123 if (parameterIndex <= this.currentParams.length) {
1124 this.currentParams[parameterIndex - 1] = x;
1125 }
1126 } catch (SQLException e) {
1127 manageException(e);
1128 throw generateException(e);
1129 }
1130 }
1131
1132 /***
1133 * Sets the designated parameter to the given <code>java.sql.Time</code>
1134 * value, using the given <code>Calendar</code> object. The driver uses
1135 * the <code>Calendar</code> object to construct an SQL <code>TIME</code>
1136 * value, which the driver then sends to the database. With a a
1137 * <code>Calendar</code> object, the driver can calculate the time taking
1138 * into account a custom timezone. If no <code>Calendar</code> object is
1139 * specified, the driver uses the default timezone, which is that of the
1140 * virtual machine running the application.
1141 *
1142 * @param parameterIndex
1143 * the first parameter is 1, the second is 2, ...
1144 * @param x
1145 * the parameter value
1146 * @param cal
1147 * the <code>Calendar</code> object the driver will use to
1148 * construct the time
1149 * @exception SQLException
1150 * if a database access error occurs
1151 * @since 1.2
1152 */
1153 public void setTime(int parameterIndex, Time x, Calendar cal)
1154 throws SQLException {
1155 try {
1156 ((PreparedStatement) this.realStatement).setTime(parameterIndex, x,
1157 cal);
1158 if (parameterIndex <= this.currentParams.length) {
1159 this.currentParams[parameterIndex - 1] = x;
1160 }
1161 } catch (SQLException e) {
1162 manageException(e);
1163 throw generateException(e);
1164 }
1165 }
1166
1167 /***
1168 * Sets the designated parameter to the given
1169 * <code>java.sql.Timestamp</code> value, using the given
1170 * <code>Calendar</code> object. The driver uses the <code>Calendar</code>
1171 * object to construct an SQL <code>TIMESTAMP</code> value, which the
1172 * driver then sends to the database. With a <code>Calendar</code> object,
1173 * the driver can calculate the timestamp taking into account a custom
1174 * timezone. If no <code>Calendar</code> object is specified, the driver
1175 * uses the default timezone, which is that of the virtual machine running
1176 * the application.
1177 *
1178 * @param parameterIndex
1179 * the first parameter is 1, the second is 2, ...
1180 * @param x
1181 * the parameter value
1182 * @param cal
1183 * the <code>Calendar</code> object the driver will use to
1184 * construct the timestamp
1185 * @exception SQLException
1186 * if a database access error occurs
1187 * @since 1.2
1188 */
1189 public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
1190 throws SQLException {
1191 try {
1192 ((PreparedStatement) this.realStatement).setTimestamp(
1193 parameterIndex, x, cal);
1194 if (parameterIndex <= this.currentParams.length) {
1195 this.currentParams[parameterIndex - 1] = x;
1196 }
1197 } catch (SQLException e) {
1198 manageException(e);
1199 throw generateException(e);
1200 }
1201 }
1202
1203 /***
1204 * Sets the designated parameter to SQL <code>NULL</code>. This version
1205 * of the method <code>setNull</code> should be used for user-defined
1206 * types and REF type parameters. Examples of user-defined types include:
1207 * STRUCT, DISTINCT, JAVA_OBJECT, and named array types.
1208 *
1209 * <P>
1210 * <B>Note: </B> To be portable, applications must give the SQL type code
1211 * and the fully-qualified SQL type name when specifying a NULL user-defined
1212 * or REF parameter. In the case of a user-defined type the name is the type
1213 * name of the parameter itself. For a REF parameter, the name is the type
1214 * name of the referenced type. If a JDBC driver does not need the type code
1215 * or type name information, it may ignore it.
1216 *
1217 * Although it is intended for user-defined and Ref parameters, this method
1218 * may be used to set a null parameter of any JDBC type. If the parameter
1219 * does not have a user-defined or REF type, the given typeName is ignored.
1220 *
1221 *
1222 * @param paramIndex
1223 * the first parameter is 1, the second is 2, ...
1224 * @param sqlType
1225 * a value from <code>java.sql.Types</code>
1226 * @param typeName
1227 * the fully-qualified name of an SQL user-defined type; ignored
1228 * if the parameter is not a user-defined type or REF
1229 * @exception SQLException
1230 * if a database access error occurs
1231 * @since 1.2
1232 */
1233 public void setNull(int paramIndex, int sqlType, String typeName)
1234 throws SQLException {
1235 try {
1236 ((PreparedStatement) this.realStatement).setNull(paramIndex,
1237 sqlType, typeName);
1238 if (paramIndex <= this.currentParams.length) {
1239 this.currentParams[paramIndex - 1] = null;
1240 }
1241 } catch (SQLException e) {
1242 manageException(e);
1243 throw generateException(e);
1244 }
1245 }
1246
1247 /***
1248 * Sets the designated parameter to the given <code>java.net.URL</code>
1249 * value. The driver converts this to an SQL <code>DATALINK</code> value
1250 * when it sends it to the database.
1251 *
1252 * @param parameterIndex
1253 * the first parameter is 1, the second is 2, ...
1254 * @param x
1255 * the <code>java.net.URL</code> object to be set
1256 * @exception SQLException
1257 * if a database access error occurs
1258 * @since 1.4
1259 */
1260 public void setURL(int parameterIndex, URL x) throws SQLException {
1261 try {
1262 ((PreparedStatement) this.realStatement).setURL(parameterIndex, x);
1263 if (parameterIndex <= this.currentParams.length) {
1264 this.currentParams[parameterIndex - 1] = x;
1265 }
1266 } catch (SQLException e) {
1267 manageException(e);
1268 throw generateException(e);
1269 }
1270 }
1271
1272 /***
1273 * Retrieves the number, types and properties of this
1274 * <code>PreparedStatement</code> object's parameters.
1275 *
1276 * @return a <code>ParameterMetaData</code> object that contains
1277 * information about the number, types and properties of this
1278 * <code>PreparedStatement</code> object's parameters
1279 * @exception SQLException
1280 * if a database access error occurs
1281 * @see ParameterMetaData
1282 * @since 1.4
1283 *
1284 */
1285 public ParameterMetaData getParameterMetaData() throws SQLException {
1286 try {
1287 return ((PreparedStatement) this.realStatement)
1288 .getParameterMetaData();
1289 } catch (SQLException e) {
1290 manageException(e);
1291 throw generateException(e);
1292 }
1293 }
1294 }