1 import java.io.InputStream;
2 import java.io.Reader;
3 import java.net.URL;
4 import java.sql.Connection;
5 import java.sql.NClob;
6 import java.sql.ParameterMetaData;
7 import java.sql.PreparedStatement;
8 import java.sql.ResultSet;
9 import java.sql.RowId;
10 import java.sql.SQLException;
11 import java.sql.SQLXML;
12 import java.util.ArrayList;
13 import java.util.Date;
14 import java.util.StringTokenizer;
15
16 /**
17 * A <code>LoggableStatement<code> is a {@link java.sql.PreparedStatement PreparedStatement} with added logging capability.
18 * <p>
19 * In addition to the methods declared in <code>PreparedStatement</code>,
20 * <code>LoggableStatement<code> provides a method {@link #getQueryString} which can be used to get the query string in a format
21 * suitable for logging.
22 *
23 * @author Jens Wyke (jens.wyke@se.ibm.com)
24 *
25 */
26 public class LoggableStatement implements PreparedStatement {
27
28 /**
29 * used for storing parameter values needed for producing log
30 */
31 private ArrayList parameterValues;
32
33 /**
34 *the query string with question marks as parameter placeholders
35 */
36 private String sqlTemplate;
37
38 /**
39 * a statement created from a real database connection
40 */
41 private PreparedStatement wrappedStatement;
42
43 /**
44 * Constructs a LoggableStatement.
45 *
46 * Creates {@link java.sql.PreparedStatement PreparedStatement} with the query string <code>sql</code> using
47 * the specified <code>connection</code> by calling {@link java.sql.Connection#prepareStatement(String)}.
48 * <p>
49 * Whenever a call is made to this <code>LoggableStatement</code> it is forwarded to the prepared statment created from
50 * <code>connection</code> after first saving relevant parameters for use in logging output.
51 *
52 * @param Connection java.sql.Connection a JDBC-connection to be used for obtaining a "real statement"
53 * @param sql java.lang.String thw sql to exectute
54 * @exception java.sql.SQLException if a <code>PreparedStatement</code> cannot be created
55 * using the supplied <code>connection</code> and <code>sql</code>
56 */
57
58 public LoggableStatement(Connection connection, String sql)
59 throws SQLException {
60 wrappedStatement = connection.prepareStatement(sql);
61 sqlTemplate = sql;
62 parameterValues = new ArrayList();
63 }
64
65 /**
66 * JDBC 2.0
67 *
68 * Adds a set of parameters to the batch.
69 *
70 * @exception SQLException if a database access error occurs
71 * @see Statement#addBatch
72 */
73 public void addBatch() throws java.sql.SQLException {
74 wrappedStatement.addBatch();
75 }
76 /**
77 * JDBC 2.0
78 *
79 * Adds a SQL command to the current batch of commmands for the statement.
80 * This method is optional.
81 *
82 * @param sql typically this is a static SQL INSERT or UPDATE statement
83 * @exception SQLException if a database access error occurs, or the
84 * driver does not support batch statements
85 */
86 public void addBatch(String sql) throws java.sql.SQLException {
87 wrappedStatement.addBatch(sql);
88 }
89 /**
90 * Cancels this <code>Statement</code> object if both the DBMS and
91 * driver support aborting an SQL statement.
92 * This method can be used by one thread to cancel a statement that
93 * is being executed by another thread.
94 *
95 * @exception SQLException if a database access error occurs
96 */
97 public void cancel() throws SQLException {
98 wrappedStatement.cancel();
99 }
100 /**
101 * JDBC 2.0
102 *
103 * Makes the set of commands in the current batch empty.
104 * This method is optional.
105 *
106 * @exception SQLException if a database access error occurs or the
107 * driver does not support batch statements
108 */
109 public void clearBatch() throws java.sql.SQLException {
110 wrappedStatement.clearBatch();
111 }
112 /**
113 * Clears the current parameter values immediately.
114 * <P>In general, parameter values remain in force for repeated use of a
115 * Statement. Setting a parameter value automatically clears its
116 * previous value. However, in some cases it is useful to immediately
117 * release the resources used by the current parameter values; this can
118 * be done by calling clearParameters.
119 *
120 * @exception SQLException if a database access error occurs
121 */
122 public void clearParameters() throws java.sql.SQLException {
123 wrappedStatement.clearParameters();
124 }
125 /**
126 * Clears all the warnings reported on this <code>Statement</code>
127 * object. After a call to this method,
128 * the method <code>getWarnings</code> will return
129 * null until a new warning is reported for this Statement.
130 *
131 * @exception SQLException if a database access error occurs
132 */
133 public void clearWarnings() throws java.sql.SQLException {
134 wrappedStatement.clearWarnings();
135 }
136 /**
137 * Releases this <code>Statement</code> object's database
138 * and JDBC resources immediately instead of waiting for
139 * this to happen when it is automatically closed.
140 * It is generally good practice to release resources as soon as
141 * you are finished with them to avoid tying up database
142 * resources.
143 * <P><B>Note:</B> A Statement is automatically closed when it is
144 * garbage collected. When a Statement is closed, its current
145 * ResultSet, if one exists, is also closed.
146 *
147 * @exception SQLException if a database access error occurs
148 */
149 public void close() throws java.sql.SQLException {
150 wrappedStatement.close();
151 }
152 /**
153 * Executes any kind of SQL statement.
154 * Some prepared statements return multiple results; the execute
155 * method handles these complex statements as well as the simpler
156 * form of statements handled by executeQuery and executeUpdate.
157 *
158 * @exception SQLException if a database access error occurs
159 * @see Statement#execute
160 */
161 public boolean execute() throws java.sql.SQLException {
162 return wrappedStatement.execute();
163 }
164 /**
165 * Executes a SQL statement that may return multiple results.
166 * Under some (uncommon) situations a single SQL statement may return
167 * multiple result sets and/or update counts. Normally you can ignore
168 * this unless you are (1) executing a stored procedure that you know may
169 * return multiple results or (2) you are dynamically executing an
170 * unknown SQL string. The methods <code>execute</code>,
171 * <code>getMoreResults</code>, <code>getResultSet</code>,
172 * and <code>getUpdateCount</code> let you navigate through multiple results.
173 *
174 * The <code>execute</code> method executes a SQL statement and indicates the
175 * form of the first result. You can then use getResultSet or
176 * getUpdateCount to retrieve the result, and getMoreResults to
177 * move to any subsequent result(s).
178 *
179 * @param sql any SQL statement
180 * @return true if the next result is a ResultSet; false if it is
181 * an update count or there are no more results
182 * @exception SQLException if a database access error occurs
183 * @see #getResultSet
184 * @see #getUpdateCount
185 * @see #getMoreResults
186 */
187 public boolean execute(String sql) throws java.sql.SQLException {
188 return wrappedStatement.execute(sql);
189 }
190 /**
191 * JDBC 2.0
192 *
193 * Submits a batch of commands to the database for execution.
194 * This method is optional.
195 *
196 * @return an array of update counts containing one element for each
197 * command in the batch. The array is ordered according
198 * to the order in which commands were inserted into the batch.
199 * @exception SQLException if a database access error occurs or the
200 * driver does not support batch statements
201 */
202 public int[] executeBatch() throws java.sql.SQLException {
203 return wrappedStatement.executeBatch();
204 }
205 /**
206 * Executes the SQL query in this <code>PreparedStatement</code> object
207 * and returns the result set generated by the query.
208 *
209 * @return a ResultSet that contains the data produced by the
210 * query; never null
211 * @exception SQLException if a database access error occurs
212 */
213 public java.sql.ResultSet executeQuery() throws java.sql.SQLException {
214 return wrappedStatement.executeQuery();
215 }
216 /**
217 * Executes a SQL statement that returns a single ResultSet.
218 *
219 * @param sql typically this is a static SQL SELECT statement
220 * @return a ResultSet that contains the data produced by the
221 * query; never null
222 * @exception SQLException if a database access error occurs
223 */
224 public java.sql.ResultSet executeQuery(String sql)
225 throws java.sql.SQLException {
226 return wrappedStatement.executeQuery(sql);
227 }
228 /**
229 * Executes the SQL INSERT, UPDATE or DELETE statement
230 * in this <code>PreparedStatement</code> object.
231 * In addition,
232 * SQL statements that return nothing, such as SQL DDL statements,
233 * can be executed.
234 *
235 * @return either the row count for INSERT, UPDATE or DELETE statements;
236 * or 0 for SQL statements that return nothing
237 * @exception SQLException if a database access error occurs
238 */
239 public int executeUpdate() throws java.sql.SQLException {
240 return wrappedStatement.executeUpdate();
241 }
242 /**
243 * Executes an SQL INSERT, UPDATE or DELETE statement. In addition,
244 * SQL statements that return nothing, such as SQL DDL statements,
245 * can be executed.
246 *
247 * @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
248 * statement that returns nothing
249 * @return either the row count for INSERT, UPDATE or DELETE or 0
250 * for SQL statements that return nothing
251 * @exception SQLException if a database access error occurs
252 */
253 public int executeUpdate(String sql) throws java.sql.SQLException {
254 return wrappedStatement.executeUpdate(sql);
255 }
256 /**
257 * JDBC 2.0
258 *
259 * Returns the <code>Connection</code> object
260 * that produced this <code>Statement</code> object.
261 * @return the connection that produced this statement
262 * @exception SQLException if a database access error occurs
263 */
264 public java.sql.Connection getConnection() throws java.sql.SQLException {
265 return wrappedStatement.getConnection();
266 }
267 /**
268 * JDBC 2.0
269 *
270 * Retrieves the direction for fetching rows from
271 * database tables that is the default for result sets
272 * generated from this <code>Statement</code> object.
273 * If this <code>Statement</code> object has not set
274 * a fetch direction by calling the method <code>setFetchDirection</code>,
275 * the return value is implementation-specific.
276 *
277 * @return the default fetch direction for result sets generated
278 * from this <code>Statement</code> object
279 * @exception SQLException if a database access error occurs
280 */
281 public int getFetchDirection() throws java.sql.SQLException {
282 return wrappedStatement.getFetchDirection();
283 }
284 /**
285 * JDBC 2.0
286 *
287 * Retrieves the number of result set rows that is the default
288 * fetch size for result sets
289 * generated from this <code>Statement</code> object.
290 * If this <code>Statement</code> object has not set
291 * a fetch size by calling the method <code>setFetchSize</code>,
292 * the return value is implementation-specific.
293 * @return the default fetch size for result sets generated
294 * from this <code>Statement</code> object
295 * @exception SQLException if a database access error occurs
296 */
297 public int getFetchSize() throws java.sql.SQLException {
298 return wrappedStatement.getFetchSize();
299 }
300 /**
301 * Returns the maximum number of bytes allowed
302 * for any column value.
303 * This limit is the maximum number of bytes that can be
304 * returned for any column value.
305 * The limit applies only to BINARY,
306 * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR
307 * columns. If the limit is exceeded, the excess data is silently
308 * discarded.
309 *
310 * @return the current max column size limit; zero means unlimited
311 * @exception SQLException if a database access error occurs
312 */
313 public int getMaxFieldSize() throws java.sql.SQLException {
314 return wrappedStatement.getMaxFieldSize();
315 }
316 /**
317 * Retrieves the maximum number of rows that a
318 * ResultSet can contain. If the limit is exceeded, the excess
319 * rows are silently dropped.
320 *
321 * @return the current max row limit; zero means unlimited
322 * @exception SQLException if a database access error occurs
323 */
324 public int getMaxRows() throws java.sql.SQLException {
325 return wrappedStatement.getMaxRows();
326 }
327 /**
328 * JDBC 2.0
329 *
330 * Gets the number, types and properties of a ResultSet's columns.
331 *
332 * @return the description of a ResultSet's columns
333 * @exception SQLException if a database access error occurs
334 */
335 public java.sql.ResultSetMetaData getMetaData()
336 throws java.sql.SQLException {
337 return wrappedStatement.getMetaData();
338 }
339 /**
340 * Moves to a Statement's next result. It returns true if
341 * this result is a ResultSet. This method also implicitly
342 * closes any current ResultSet obtained with getResultSet.
343 *
344 * There are no more results when (!getMoreResults() &&
345 * (getUpdateCount() == -1)
346 *
347 * @return true if the next result is a ResultSet; false if it is
348 * an update count or there are no more results
349 * @exception SQLException if a database access error occurs
350 * @see #execute
351 */
352 public boolean getMoreResults() throws java.sql.SQLException {
353 return wrappedStatement.getMoreResults();
354 }
355 /**
356 * Retrieves the number of seconds the driver will
357 * wait for a Statement to execute. If the limit is exceeded, a
358 * SQLException is thrown.
359 *
360 * @return the current query timeout limit in seconds; zero means unlimited
361 * @exception SQLException if a database access error occurs
362 */
363 public int getQueryTimeout() throws java.sql.SQLException {
364 return wrappedStatement.getQueryTimeout();
365 }
366 /**
367 * Returns the current result as a <code>ResultSet</code> object.
368 * This method should be called only once per result.
369 *
370 * @return the current result as a ResultSet; null if the result
371 * is an update count or there are no more results
372 * @exception SQLException if a database access error occurs
373 * @see #execute
374 */
375 public java.sql.ResultSet getResultSet() throws java.sql.SQLException {
376 return wrappedStatement.getResultSet();
377 }
378 /**
379 * JDBC 2.0
380 *
381 * Retrieves the result set concurrency.
382 */
383 public int getResultSetConcurrency() throws java.sql.SQLException {
384 return wrappedStatement.getResultSetConcurrency();
385 }
386 /**
387 * JDBC 2.0
388 *
389 * Determine the result set type.
390 */
391 public int getResultSetType() throws java.sql.SQLException {
392 return wrappedStatement.getResultSetType();
393 }
394 /**
395 * Returns the current result as an update count;
396 * if the result is a ResultSet or there are no more results, -1
397 * is returned.
398 * This method should be called only once per result.
399 *
400 * @return the current result as an update count; -1 if it is a
401 * ResultSet or there are no more results
402 * @exception SQLException if a database access error occurs
403 * @see #execute
404 */
405 public int getUpdateCount() throws java.sql.SQLException {
406 return wrappedStatement.getUpdateCount();
407 }
408 /**
409 * Retrieves the first warning reported by calls on this Statement.
410 * Subsequent Statement warnings will be chained to this
411 * SQLWarning.
412 *
413 * <p>The warning chain is automatically cleared each time
414 * a statement is (re)executed.
415 *
416 * <P><B>Note:</B> If you are processing a ResultSet, any
417 * warnings associated with ResultSet reads will be chained on the
418 * ResultSet object.
419 *
420 * @return the first SQLWarning or null
421 * @exception SQLException if a database access error occurs
422 */
423 public java.sql.SQLWarning getWarnings() throws java.sql.SQLException {
424 return wrappedStatement.getWarnings();
425 }
426 /**
427 * JDBC 2.0
428 *
429 * Sets an Array parameter.
430 *
431 * @param i the first parameter is 1, the second is 2, ...
432 * @param x an object representing an SQL array
433 * @exception SQLException if a database access error occurs
434 */
435 public void setArray(int i, java.sql.Array x)
436 throws java.sql.SQLException {
437
438 wrappedStatement.setArray(i, x);
439 saveQueryParamValue(i, x);
440
441 }
442 /**
443 * Sets the designated parameter to the given input stream, which will have
444 * the specified number of bytes.
445 * When a very large ASCII value is input to a LONGVARCHAR
446 * parameter, it may be more practical to send it via a
447 * java.io.InputStream. JDBC will read the data from the stream
448 * as needed, until it reaches end-of-file. The JDBC driver will
449 * do any necessary conversion from ASCII to the database char format.
450 *
451 * <P><B>Note:</B> This stream object can either be a standard
452 * Java stream object or your own subclass that implements the
453 * standard interface.
454 *
455 * @param parameterIndex the first parameter is 1, the second is 2, ...
456 * @param x the Java input stream that contains the ASCII parameter value
457 * @param length the number of bytes in the stream
458 * @exception SQLException if a database access error occurs
459 */
460 public void setAsciiStream(
461 int parameterIndex,
462 java.io.InputStream x,
463 int length)
464 throws java.sql.SQLException {
465
466 wrappedStatement.setAsciiStream(parameterIndex, x, length);
467 saveQueryParamValue(parameterIndex, x);
468 }
469 /**
470 * Sets the designated parameter to a java.lang.BigDecimal value.
471 * The driver converts this to an SQL NUMERIC value when
472 * it sends it to the database.
473 *
474 * @param parameterIndex the first parameter is 1, the second is 2, ...
475 * @param x the parameter value
476 * @exception SQLException if a database access error occurs
477 */
478 public void setBigDecimal(int parameterIndex, java.math.BigDecimal x)
479 throws java.sql.SQLException {
480 wrappedStatement.setBigDecimal(parameterIndex, x);
481 saveQueryParamValue(parameterIndex, x);
482
483 }
484 /**
485 * Sets the designated parameter to the given input stream, which will have
486 * the specified number of bytes.
487 * When a very large binary value is input to a LONGVARBINARY
488 * parameter, it may be more practical to send it via a
489 * java.io.InputStream. JDBC will read the data from the stream
490 * as needed, until it reaches end-of-file.
491 *
492 * <P><B>Note:</B> This stream object can either be a standard
493 * Java stream object or your own subclass that implements the
494 * standard interface.
495 *
496 * @param parameterIndex the first parameter is 1, the second is 2, ...
497 * @param x the java input stream which contains the binary parameter value
498 * @param length the number of bytes in the stream
499 * @exception SQLException if a database access error occurs
500 */
501 public void setBinaryStream(
502 int parameterIndex,
503 java.io.InputStream x,
504 int length)
505 throws java.sql.SQLException {
506 wrappedStatement.setBinaryStream(parameterIndex, x, length);
507 saveQueryParamValue(parameterIndex, x);
508
509 }
510 /**
511 * JDBC 2.0
512 *
513 * Sets a BLOB parameter.
514 *
515 * @param i the first parameter is 1, the second is 2, ...
516 * @param x an object representing a BLOB
517 * @exception SQLException if a database access error occurs
518 */
519 public void setBlob(int i, java.sql.Blob x) throws java.sql.SQLException {
520 wrappedStatement.setBlob(i, x);
521 saveQueryParamValue(i, x);
522 }
523 /**
524 * Sets the designated parameter to a Java boolean value. The driver converts this
525 * to an SQL BIT value when it sends it to the database.
526 *
527 * @param parameterIndex the first parameter is 1, the second is 2, ...
528 * @param x the parameter value
529 * @exception SQLException if a database access error occurs
530 */
531 public void setBoolean(int parameterIndex, boolean x)
532 throws java.sql.SQLException {
533 wrappedStatement.setBoolean(parameterIndex, x);
534 saveQueryParamValue(parameterIndex, new Boolean(x));
535
536 }
537 /**
538 * Sets the designated parameter to a Java byte value. The driver converts this
539 * to an SQL TINYINT value when it sends it to the database.
540 *
541 * @param parameterIndex the first parameter is 1, the second is 2, ...
542 * @param x the parameter value
543 * @exception SQLException if a database access error occurs
544 */
545 public void setByte(int parameterIndex, byte x)
546 throws java.sql.SQLException {
547 wrappedStatement.setByte(parameterIndex, x);
548 saveQueryParamValue(parameterIndex, new Integer(x));
549 }
550 /**
551 * Sets the designated parameter to a Java array of bytes. The driver converts
552 * this to an SQL VARBINARY or LONGVARBINARY (depending on the
553 * argument's size relative to the driver's limits on VARBINARYs)
554 * when it sends it to the database.
555 *
556 * @param parameterIndex the first parameter is 1, the second is 2, ...
557 * @param x the parameter value
558 * @exception SQLException if a database access error occurs
559 */
560 public void setBytes(int parameterIndex, byte[] x)
561 throws java.sql.SQLException {
562 wrappedStatement.setBytes(parameterIndex, x);
563 saveQueryParamValue(parameterIndex, x);
564 }
565 /**
566 * JDBC 2.0
567 *
568 * Sets the designated parameter to the given <code>Reader</code>
569 * object, which is the given number of characters long.
570 * When a very large UNICODE value is input to a LONGVARCHAR
571 * parameter, it may be more practical to send it via a
572 * java.io.Reader. JDBC will read the data from the stream
573 * as needed, until it reaches end-of-file. The JDBC driver will
574 * do any necessary conversion from UNICODE to the database char format.
575 *
576 * <P><B>Note:</B> This stream object can either be a standard
577 * Java stream object or your own subclass that implements the
578 * standard interface.
579 *
580 * @param parameterIndex the first parameter is 1, the second is 2, ...
581 * @param x the java reader which contains the UNICODE data
582 * @param length the number of characters in the stream
583 * @exception SQLException if a database access error occurs
584 */
585 public void setCharacterStream(
586 int parameterIndex,
587 java.io.Reader reader,
588 int length)
589 throws java.sql.SQLException {
590 wrappedStatement.setCharacterStream(parameterIndex, reader, length);
591 saveQueryParamValue(parameterIndex, reader);
592
593 }
594 /**
595 * JDBC 2.0
596 *
597 * Sets a CLOB parameter.
598 *
599 * @param i the first parameter is 1, the second is 2, ...
600 * @param x an object representing a CLOB
601 * @exception SQLException if a database access error occurs
602 */
603 public void setClob(int i, java.sql.Clob x) throws java.sql.SQLException {
604 wrappedStatement.setClob(i, x);
605 saveQueryParamValue(i, x);
606
607 }
608 /**
609 * Defines the SQL cursor name that will be used by
610 * subsequent Statement <code>execute</code> methods. This name can then be
611 * used in SQL positioned update/delete statements to identify the
612 * current row in the ResultSet generated by this statement. If
613 * the database doesn't support positioned update/delete, this
614 * method is a noop. To insure that a cursor has the proper isolation
615 * level to support updates, the cursor's SELECT statement should be
616 * of the form 'select for update ...'. If the 'for update' phrase is
617 * omitted, positioned updates may fail.
618 *
619 * <P><B>Note:</B> By definition, positioned update/delete
620 * execution must be done by a different Statement than the one
621 * which generated the ResultSet being used for positioning. Also,
622 * cursor names must be unique within a connection.
623 *
624 * @param name the new cursor name, which must be unique within
625 * a connection
626 * @exception SQLException if a database access error occurs
627 */
628 public void setCursorName(String name) throws java.sql.SQLException {
629 wrappedStatement.setCursorName(name);
630
631 }
632 /**
633 * Sets the designated parameter to a java.sql.Date value. The driver converts this
634 * to an SQL DATE value when it sends it to the database.
635 *
636 * @param parameterIndex the first parameter is 1, the second is 2, ...
637 * @param x the parameter value
638 * @exception SQLException if a database access error occurs
639 */
640 public void setDate(int parameterIndex, java.sql.Date x)
641 throws java.sql.SQLException {
642
643 wrappedStatement.setDate(parameterIndex, x);
644 saveQueryParamValue(parameterIndex, x);
645 }
646 /**
647 * JDBC 2.0
648 *
649 * Sets the designated parameter to a java.sql.Date value,
650 * using the given <code>Calendar</code> object. The driver uses
651 * the <code>Calendar</code> object to construct an SQL DATE,
652 * which the driver then sends to the database. With a
653 * a <code>Calendar</code> object, the driver can calculate the date
654 * taking into account a custom timezone and locale. If no
655 * <code>Calendar</code> object is specified, the driver uses the default
656 * timezone and locale.
657 *
658 * @param parameterIndex the first parameter is 1, the second is 2, ...
659 * @param x the parameter value
660 * @param cal the <code>Calendar</code> object the driver will use
661 * to construct the date
662 * @exception SQLException if a database access error occurs
663 */
664 public void setDate(
665 int parameterIndex,
666 java.sql.Date x,
667 java.util.Calendar cal)
668 throws java.sql.SQLException {
669 wrappedStatement.setDate(parameterIndex, x, cal);
670 saveQueryParamValue(parameterIndex, x);
671 }
672 /**
673 * Sets the designated parameter to a Java double value. The driver converts this
674 * to an SQL DOUBLE value when it sends it to the database.
675 *
676 * @param parameterIndex the first parameter is 1, the second is 2, ...
677 * @param x the parameter value
678 * @exception SQLException if a database access error occurs
679 */
680 public void setDouble(int parameterIndex, double x)
681 throws java.sql.SQLException {
682 wrappedStatement.setDouble(parameterIndex, x);
683 saveQueryParamValue(parameterIndex, new Double(x));
684 }
685 /**
686 * Sets escape processing on or off.
687 * If escape scanning is on (the default), the driver will do
688 * escape substitution before sending the SQL to the database.
689 *
690 * Note: Since prepared statements have usually been parsed prior
691 * to making this call, disabling escape processing for prepared
692 * statements will have no effect.
693 *
694 * @param enable true to enable; false to disable
695 * @exception SQLException if a database access error occurs
696 */
697 public void setEscapeProcessing(boolean enable)
698 throws java.sql.SQLException {
699 wrappedStatement.setEscapeProcessing(enable);
700
701 }
702 /**
703 * JDBC 2.0
704 *
705 * Gives the driver a hint as to the direction in which
706 * the rows in a result set
707 * will be processed. The hint applies only to result sets created
708 * using this Statement object. The default value is
709 * ResultSet.FETCH_FORWARD.
710 * <p>Note that this method sets the default fetch direction for
711 * result sets generated by this <code>Statement</code> object.
712 * Each result set has its own methods for getting and setting
713 * its own fetch direction.
714 * @param direction the initial direction for processing rows
715 * @exception SQLException if a database access error occurs
716 * or the given direction
717 * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
718 * ResultSet.FETCH_UNKNOWN
719 */
720 public void setFetchDirection(int direction) throws java.sql.SQLException {
721 wrappedStatement.setFetchDirection(direction);
722 }
723 /**
724 * JDBC 2.0
725 *
726 * Gives the JDBC driver a hint as to the number of rows that should
727 * be fetched from the database when more rows are needed. The number
728 * of rows specified affects only result sets created using this
729 * statement. If the value specified is zero, then the hint is ignored.
730 * The default value is zero.
731 *
732 * @param rows the number of rows to fetch
733 * @exception SQLException if a database access error occurs, or the
734 * condition 0 <= rows <= this.getMaxRows() is not satisfied.
735 */
736 public void setFetchSize(int rows) throws java.sql.SQLException {
737 wrappedStatement.setFetchSize(rows);
738 }
739 /**
740 * Sets the designated parameter to a Java float value. The driver converts this
741 * to an SQL FLOAT value when it sends it to the database.
742 *
743 * @param parameterIndex the first parameter is 1, the second is 2, ...
744 * @param x the parameter value
745 * @exception SQLException if a database access error occurs
746 */
747 public void setFloat(int parameterIndex, float x)
748 throws java.sql.SQLException {
749 wrappedStatement.setFloat(parameterIndex, x);
750 saveQueryParamValue(parameterIndex, new Float(x));
751
752 }
753 /**
754 * Sets the designated parameter to a Java int value. The driver converts this
755 * to an SQL INTEGER value when it sends it to the database.
756 *
757 * @param parameterIndex the first parameter is 1, the second is 2, ...
758 * @param x the parameter value
759 * @exception SQLException if a database access error occurs
760 */
761 public void setInt(int parameterIndex, int x)
762 throws java.sql.SQLException {
763 wrappedStatement.setInt(parameterIndex, x);
764 saveQueryParamValue(parameterIndex, new Integer(x));
765 }
766 /**
767 * Sets the designated parameter to a Java long value. The driver converts this
768 * to an SQL BIGINT value when it sends it to the database.
769 *
770 * @param parameterIndex the first parameter is 1, the second is 2, ...
771 * @param x the parameter value
772 * @exception SQLException if a database access error occurs
773 */
774 public void setLong(int parameterIndex, long x)
775 throws java.sql.SQLException {
776 wrappedStatement.setLong(parameterIndex, x);
777 saveQueryParamValue(parameterIndex, new Long(x));
778
779 }
780 /**
781 * Sets the limit for the maximum number of bytes in a column to
782 * the given number of bytes. This is the maximum number of bytes
783 * that can be returned for any column value. This limit applies
784 * only to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and
785 * LONGVARCHAR fields. If the limit is exceeded, the excess data
786 * is silently discarded. For maximum portability, use values
787 * greater than 256.
788 *
789 * @param max the new max column size limit; zero means unlimited
790 * @exception SQLException if a database access error occurs
791 */
792 public void setMaxFieldSize(int max) throws java.sql.SQLException {
793 wrappedStatement.setMaxFieldSize(max);
794
795 }
796 /**
797 * Sets the limit for the maximum number of rows that any
798 * ResultSet can contain to the given number.
799 * If the limit is exceeded, the excess
800 * rows are silently dropped.
801 *
802 * @param max the new max rows limit; zero means unlimited
803 * @exception SQLException if a database access error occurs
804 */
805 public void setMaxRows(int max) throws java.sql.SQLException {
806 wrappedStatement.setMaxRows(max);
807 }
808 /**
809 * Sets the designated parameter to SQL NULL.
810 *
811 * <P><B>Note:</B> You must specify the parameter's SQL type.
812 *
813 * @param parameterIndex the first parameter is 1, the second is 2, ...
814 * @param sqlType the SQL type code defined in java.sql.Types
815 * @exception SQLException if a database access error occurs
816 */
817 public void setNull(int parameterIndex, int sqlType)
818 throws java.sql.SQLException {
819 wrappedStatement.setNull(parameterIndex, sqlType);
820 saveQueryParamValue(parameterIndex, null);
821 }
822 /**
823 * JDBC 2.0
824 *
825 * Sets the designated parameter to SQL NULL. This version of setNull should
826 * be used for user-named types and REF type parameters. Examples
827 * of user-named types include: STRUCT, DISTINCT, JAVA_OBJECT, and
828 * named array types.
829 *
830 * <P><B>Note:</B> To be portable, applications must give the
831 * SQL type code and the fully-qualified SQL type name when specifying
832 * a NULL user-defined or REF parameter. In the case of a user-named type
833 * the name is the type name of the parameter itself. For a REF
834 * parameter the name is the type name of the referenced type. If
835 * a JDBC driver does not need the type code or type name information,
836 * it may ignore it.
837 *
838 * Although it is intended for user-named and Ref parameters,
839 * this method may be used to set a null parameter of any JDBC type.
840 * If the parameter does not have a user-named or REF type, the given
841 * typeName is ignored.
842 *
843 *
844 * @param parameterIndex the first parameter is 1, the second is 2, ...
845 * @param sqlType a value from java.sql.Types
846 * @param typeName the fully-qualified name of an SQL user-named type,
847 * ignored if the parameter is not a user-named type or REF
848 * @exception SQLException if a database access error occurs
849 */
850 public void setNull(int paramIndex, int sqlType, String typeName)
851 throws java.sql.SQLException {
852 wrappedStatement.setNull(paramIndex, sqlType, typeName);
853 saveQueryParamValue(paramIndex, null);
854
855 }
856 /**
857 * <p>Sets the value of a parameter using an object; use the
858 * java.lang equivalent objects for integral values.
859 *
860 * <p>The JDBC specification specifies a standard mapping from
861 * Java Object types to SQL types. The given argument java object
862 * will be converted to the corresponding SQL type before being
863 * sent to the database.
864 *
865 * <p>Note that this method may be used to pass datatabase-
866 * specific abstract data types, by using a Driver-specific Java
867 * type.
868 *
869 * If the object is of a class implementing SQLData,
870 * the JDBC driver should call its method <code>writeSQL</code> to write it
871 * to the SQL data stream.
872 * If, on the other hand, the object is of a class implementing
873 * Ref, Blob, Clob, Struct,
874 * or Array, then the driver should pass it to the database as a value of the
875 * corresponding SQL type.
876 *
877 * This method throws an exception if there is an ambiguity, for example, if the
878 * object is of a class implementing more than one of those interfaces.
879 *
880 * @param parameterIndex the first parameter is 1, the second is 2, ...
881 * @param x the object containing the input parameter value
882 * @exception SQLException if a database access error occurs
883 */
884 public void setObject(int parameterIndex, Object x)
885 throws java.sql.SQLException {
886 wrappedStatement.setObject(parameterIndex, x);
887 saveQueryParamValue(parameterIndex, x);
888 }
889 /**
890 * Sets the value of the designated parameter with the given object.
891 * This method is like setObject above, except that it assumes a scale of zero.
892 *
893 * @param parameterIndex the first parameter is 1, the second is 2, ...
894 * @param x the object containing the input parameter value
895 * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
896 * sent to the database
897 * @exception SQLException if a database access error occurs
898 */
899 public void setObject(int parameterIndex, Object x, int targetSqlType)
900 throws java.sql.SQLException {
901 wrappedStatement.setObject(parameterIndex, x, targetSqlType);
902 saveQueryParamValue(parameterIndex, x);
903 }
904 /**
905 * <p>Sets the value of a parameter using an object. The second
906 * argument must be an object type; for integral values, the
907 * java.lang equivalent objects should be used.
908 *
909 * <p>The given Java object will be converted to the targetSqlType
910 * before being sent to the database.
911 *
912 * If the object has a custom mapping (is of a class implementing SQLData),
913 * the JDBC driver should call its method <code>writeSQL</code> to write it
914 * to the SQL data stream.
915 * If, on the other hand, the object is of a class implementing
916 * Ref, Blob, Clob, Struct,
917 * or Array, the driver should pass it to the database as a value of the
918 * corresponding SQL type.
919 *
920 * <p>Note that this method may be used to pass datatabase-
921 * specific abstract data types.
922 *
923 * @param parameterIndex the first parameter is 1, the second is 2, ...
924 * @param x the object containing the input parameter value
925 * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
926 * sent to the database. The scale argument may further qualify this type.
927 * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
928 * this is the number of digits after the decimal point. For all other
929 * types, this value will be ignored.
930 * @exception SQLException if a database access error occurs
931 * @see Types
932 */
933 public void setObject(
934 int parameterIndex,
935 Object x,
936 int targetSqlType,
937 int scale)
938 throws java.sql.SQLException {
939
940 wrappedStatement.setObject(parameterIndex, x, targetSqlType, scale);
941 saveQueryParamValue(parameterIndex, x);
942 }
943 /**
944 * Sets the number of seconds the driver will
945 * wait for a Statement to execute to the given number of seconds.
946 * If the limit is exceeded, a SQLException is thrown.
947 *
948 * @param seconds the new query timeout limit in seconds; zero means
949 * unlimited
950 * @exception SQLException if a database access error occurs
951 */
952 public void setQueryTimeout(int seconds) throws java.sql.SQLException {
953 wrappedStatement.setQueryTimeout(seconds);
954 }
955 /**
956 * JDBC 2.0
957 *
958 * Sets a REF(<structured-type>) parameter.
959 *
960 * @param i the first parameter is 1, the second is 2, ...
961 * @param x an object representing data of an SQL REF Type
962 * @exception SQLException if a database access error occurs
963 */
964 public void setRef(int i, java.sql.Ref x) throws java.sql.SQLException {
965 wrappedStatement.setRef(i, x);
966 saveQueryParamValue(i, x);
967
968 }
969 /**
970 * Sets the designated parameter to a Java short value. The driver converts this
971 * to an SQL SMALLINT value when it sends it to the database.
972 *
973 * @param parameterIndex the first parameter is 1, the second is 2, ...
974 * @param x the parameter value
975 * @exception SQLException if a database access error occurs
976 */
977 public void setShort(int parameterIndex, short x)
978 throws java.sql.SQLException {
979 wrappedStatement.setShort(parameterIndex, x);
980 saveQueryParamValue(parameterIndex, new Integer(x));
981 }
982 /**
983 * Sets the designated parameter to a Java String value. The driver converts this
984 * to an SQL VARCHAR or LONGVARCHAR value (depending on the argument's
985 * size relative to the driver's limits on VARCHARs) when it sends
986 * it to the database.
987 *
988 * @param parameterIndex the first parameter is 1, the second is 2, ...
989 * @param x the parameter value
990 * @exception SQLException if a database access error occurs
991 */
992 public void setString(int parameterIndex, String x)
993 throws java.sql.SQLException {
994
995 wrappedStatement.setString(parameterIndex, x);
996 saveQueryParamValue(parameterIndex, x);
997 }
998 /**
999 * Sets the designated parameter to a java.sql.Time value. The driver converts this
1000 * to an SQL TIME value when it sends it to the database.
1001 *
1002 * @param parameterIndex the first parameter is 1, the second is 2, ...
1003 * @param x the parameter value
1004 * @exception SQLException if a database access error occurs
1005 */
1006 public void setTime(int parameterIndex, java.sql.Time x)
1007 throws java.sql.SQLException {
1008 wrappedStatement.setTime(parameterIndex, x);
1009 saveQueryParamValue(parameterIndex, x);
1010 }
1011 /**
1012 * JDBC 2.0
1013 *
1014 * Sets the designated parameter to a java.sql.Time value,
1015 * using the given <code>Calendar</code> object. The driver uses
1016 * the <code>Calendar</code> object to construct an SQL TIME,
1017 * which the driver then sends to the database. With a
1018 * a <code>Calendar</code> object, the driver can calculate the time
1019 * taking into account a custom timezone and locale. If no
1020 * <code>Calendar</code> object is specified, the driver uses the default
1021 * timezone and locale.
1022 *
1023 * @param parameterIndex the first parameter is 1, the second is 2, ...
1024 * @param x the parameter value
1025 * @param cal the <code>Calendar</code> object the driver will use
1026 * to construct the time
1027 * @exception SQLException if a database access error occurs
1028 */
1029 public void setTime(
1030 int parameterIndex,
1031 java.sql.Time x,
1032 java.util.Calendar cal)
1033 throws java.sql.SQLException {
1034 wrappedStatement.setTime(parameterIndex, x, cal);
1035 saveQueryParamValue(parameterIndex, x);
1036
1037 }
1038 /**
1039 * Sets the designated parameter to a java.sql.Timestamp value. The driver
1040 * converts this to an SQL TIMESTAMP value when it sends it to the
1041 * database.
1042 *
1043 * @param parameterIndex the first parameter is 1, the second is 2, ...
1044 * @param x the parameter value
1045 * @exception SQLException if a database access error occurs
1046 */
1047 public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
1048 throws java.sql.SQLException {
1049 wrappedStatement.setTimestamp(parameterIndex, x);
1050 saveQueryParamValue(parameterIndex, x);
1051 }
1052 /**
1053 * JDBC 2.0
1054 *
1055 * Sets the designated parameter to a java.sql.Timestamp value,
1056 * using the given <code>Calendar</code> object. The driver uses
1057 * the <code>Calendar</code> object to construct an SQL TIMESTAMP,
1058 * which the driver then sends to the database. With a
1059 * a <code>Calendar</code> object, the driver can calculate the timestamp
1060 * taking into account a custom timezone and locale. If no
1061 * <code>Calendar</code> object is specified, the driver uses the default
1062 * timezone and locale.
1063 *
1064 * @param parameterIndex the first parameter is 1, the second is 2, ...
1065 * @param x the parameter value
1066 * @param cal the <code>Calendar</code> object the driver will use
1067 * to construct the timestamp
1068 * @exception SQLException if a database access error occurs
1069 */
1070 public void setTimestamp(
1071 int parameterIndex,
1072 java.sql.Timestamp x,
1073 java.util.Calendar cal)
1074 throws java.sql.SQLException {
1075 wrappedStatement.setTimestamp(parameterIndex, x, cal);
1076 saveQueryParamValue(parameterIndex, x);
1077 }
1078 /**
1079 * Sets the designated parameter to the given input stream, which will have
1080 * the specified number of bytes.
1081 * When a very large UNICODE value is input to a LONGVARCHAR
1082 * parameter, it may be more practical to send it via a
1083 * java.io.InputStream. JDBC will read the data from the stream
1084 * as needed, until it reaches end-of-file. The JDBC driver will
1085 * do any necessary conversion from UNICODE to the database char format.
1086 * The byte format of the Unicode stream must be Java UTF-8, as
1087 * defined in the Java Virtual Machine Specification.
1088 *
1089 * <P><B>Note:</B> This stream object can either be a standard
1090 * Java stream object or your own subclass that implements the
1091 * standard interface.
1092 *
1093 * @param parameterIndex the first parameter is 1, the second is 2, ...
1094 * @param x the java input stream which contains the
1095 * UNICODE parameter value
1096 * @param length the number of bytes in the stream
1097 * @exception SQLException if a database access error occurs
1098 * @deprecated
1099 */
1100 public void setUnicodeStream(
1101 int parameterIndex,
1102 java.io.InputStream x,
1103 int length)
1104 throws java.sql.SQLException {
1105 wrappedStatement.setUnicodeStream(parameterIndex, x, length);
1106 saveQueryParamValue(parameterIndex, x);
1107 }
1108
1109 /**
1110 * Returns the sql statement string (question marks replaced with set parameter values)
1111 * that will be (or has been) executed by the {@link java.sql.PreparedStatement PreparedStatement} that this
1112 * <code>LoggableStatement</code> is a wrapper for.
1113 * <p>
1114 * @return java.lang.String the statemant represented by this <code>LoggableStatement</code>
1115 */
1116 public String getQueryString() {
1117
1118 StringBuffer buf = new StringBuffer();
1119 int qMarkCount = 0;
1120 ArrayList chunks = new ArrayList();
1121 StringTokenizer tok = new StringTokenizer(sqlTemplate+" ", "?");
1122 while (tok.hasMoreTokens()) {
1123 String oneChunk = tok.nextToken();
1124 buf.append(oneChunk);
1125
1126 try {
1127 Object value;
1128 if (parameterValues.size() > 1 + qMarkCount) {
1129 value = parameterValues.get(1 + qMarkCount++);
1130 } else {
1131 if (tok.hasMoreTokens()) {
1132 value = null;
1133 } else {
1134 value = "";
1135 }
1136 }
1137 buf.append("" + value);
1138 } catch (Throwable e) {
1139 buf.append(
1140 "ERROR WHEN PRODUCING QUERY STRING FOR LOG."
1141 + e.toString());
1142 // catch this without whining, if this fails the only thing wrong is probably this class
1143 }
1144 }
1145 return buf.toString().trim();
1146 }
1147
1148 /**
1149 * Saves the parameter value <code>obj</code> for the specified <code>position</code> for use in logging output
1150 *
1151 * @param position position (starting at 1) of the parameter to save
1152 * @param obj java.lang.Object the parameter value to save
1153 */
1154 private void saveQueryParamValue(int position, Object obj) {
1155 String strValue;
1156 if (obj instanceof String || obj instanceof Date) {
1157 // if we have a String or Date , include '' in the saved value
1158 strValue = "'" + obj + "'";
1159 } else {
1160
1161 if (obj == null) {
1162 // convert null to the string null
1163 strValue = "null";
1164 } else {
1165 // unknown object (includes all Numbers), just call toString
1166 strValue = obj.toString();
1167 }
1168 }
1169
1170 // if we are setting a position larger than current size of parameterValues, first make it larger
1171 while (position >= parameterValues.size()) {
1172 parameterValues.add(null);
1173 }
1174 // save the parameter
1175 parameterValues.set(position, strValue);
1176 }
1177
1178 @Override
1179 public boolean getMoreResults(int current) throws SQLException {
1180 // TODO Auto-generated method stub
1181 return false;
1182 }
1183
1184 @Override
1185 public ResultSet getGeneratedKeys() throws SQLException {
1186 // TODO Auto-generated method stub
1187 return null;
1188 }
1189
1190 @Override
1191 public int executeUpdate(String sql, int autoGeneratedKeys)
1192 throws SQLException {
1193 // TODO Auto-generated method stub
1194 return 0;
1195 }
1196
1197 @Override
1198 public int executeUpdate(String sql, int[] columnIndexes)
1199 throws SQLException {
1200 // TODO Auto-generated method stub
1201 return 0;
1202 }
1203
1204 @Override
1205 public int executeUpdate(String sql, String[] columnNames)
1206 throws SQLException {
1207 // TODO Auto-generated method stub
1208 return 0;
1209 }
1210
1211 @Override
1212 public boolean execute(String sql, int autoGeneratedKeys)
1213 throws SQLException {
1214 // TODO Auto-generated method stub
1215 return false;
1216 }
1217
1218 @Override
1219 public boolean execute(String sql, int[] columnIndexes) throws SQLException {
1220 // TODO Auto-generated method stub
1221 return false;
1222 }
1223
1224 @Override
1225 public boolean execute(String sql, String[] columnNames)
1226 throws SQLException {
1227 // TODO Auto-generated method stub
1228 return false;
1229 }
1230
1231 @Override
1232 public int getResultSetHoldability() throws SQLException {
1233 // TODO Auto-generated method stub
1234 return 0;
1235 }
1236
1237 @Override
1238 public boolean isClosed() throws SQLException {
1239 // TODO Auto-generated method stub
1240 return false;
1241 }
1242
1243 @Override
1244 public void setPoolable(boolean poolable) throws SQLException {
1245 // TODO Auto-generated method stub
1246
1247 }
1248
1249 @Override
1250 public boolean isPoolable() throws SQLException {
1251 // TODO Auto-generated method stub
1252 return false;
1253 }
1254
1255 @Override
1256 public void closeOnCompletion() throws SQLException {
1257 // TODO Auto-generated method stub
1258
1259 }
1260
1261 @Override
1262 public boolean isCloseOnCompletion() throws SQLException {
1263 // TODO Auto-generated method stub
1264 return false;
1265 }
1266
1267 @Override
1268 public <T> T unwrap(Class<T> iface) throws SQLException {
1269 // TODO Auto-generated method stub
1270 return null;
1271 }
1272
1273 @Override
1274 public boolean isWrapperFor(Class<?> iface) throws SQLException {
1275 // TODO Auto-generated method stub
1276 return false;
1277 }
1278
1279 @Override
1280 public void setURL(int parameterIndex, URL x) throws SQLException {
1281 // TODO Auto-generated method stub
1282
1283 }
1284
1285 @Override
1286 public ParameterMetaData getParameterMetaData() throws SQLException {
1287 // TODO Auto-generated method stub
1288 return null;
1289 }
1290
1291 @Override
1292 public void setRowId(int parameterIndex, RowId x) throws SQLException {
1293 // TODO Auto-generated method stub
1294
1295 }
1296
1297 @Override
1298 public void setNString(int parameterIndex, String value)
1299 throws SQLException {
1300 // TODO Auto-generated method stub
1301
1302 }
1303
1304 @Override
1305 public void setNCharacterStream(int parameterIndex, Reader value,
1306 long length) throws SQLException {
1307 // TODO Auto-generated method stub
1308
1309 }
1310
1311 @Override
1312 public void setNClob(int parameterIndex, NClob value) throws SQLException {
1313 // TODO Auto-generated method stub
1314
1315 }
1316
1317 @Override
1318 public void setClob(int parameterIndex, Reader reader, long length)
1319 throws SQLException {
1320 // TODO Auto-generated method stub
1321
1322 }
1323
1324 @Override
1325 public void setBlob(int parameterIndex, InputStream inputStream, long length)
1326 throws SQLException {
1327 // TODO Auto-generated method stub
1328
1329 }
1330
1331 @Override
1332 public void setNClob(int parameterIndex, Reader reader, long length)
1333 throws SQLException {
1334 // TODO Auto-generated method stub
1335
1336 }
1337
1338 @Override
1339 public void setSQLXML(int parameterIndex, SQLXML xmlObject)
1340 throws SQLException {
1341 // TODO Auto-generated method stub
1342
1343 }
1344
1345 @Override
1346 public void setAsciiStream(int parameterIndex, InputStream x, long length)
1347 throws SQLException {
1348 // TODO Auto-generated method stub
1349
1350 }
1351
1352 @Override
1353 public void setBinaryStream(int parameterIndex, InputStream x, long length)
1354 throws SQLException {
1355 // TODO Auto-generated method stub
1356
1357 }
1358
1359 @Override
1360 public void setCharacterStream(int parameterIndex, Reader reader,
1361 long length) throws SQLException {
1362 // TODO Auto-generated method stub
1363
1364 }
1365
1366 @Override
1367 public void setAsciiStream(int parameterIndex, InputStream x)
1368 throws SQLException {
1369 // TODO Auto-generated method stub
1370
1371 }
1372
1373 @Override
1374 public void setBinaryStream(int parameterIndex, InputStream x)
1375 throws SQLException {
1376 // TODO Auto-generated method stub
1377
1378 }
1379
1380 @Override
1381 public void setCharacterStream(int parameterIndex, Reader reader)
1382 throws SQLException {
1383 // TODO Auto-generated method stub
1384
1385 }
1386
1387 @Override
1388 public void setNCharacterStream(int parameterIndex, Reader value)
1389 throws SQLException {
1390 // TODO Auto-generated method stub
1391
1392 }
1393
1394 @Override
1395 public void setClob(int parameterIndex, Reader reader) throws SQLException {
1396 // TODO Auto-generated method stub
1397
1398 }
1399
1400 @Override
1401 public void setBlob(int parameterIndex, InputStream inputStream)
1402 throws SQLException {
1403 // TODO Auto-generated method stub
1404
1405 }
1406
1407 @Override
1408 public void setNClob(int parameterIndex, Reader reader) throws SQLException {
1409 // TODO Auto-generated method stub
1410
1411 }
1412 }