001    package org.rakeshv.dbutils;
002    
003    import java.sql.Connection;
004    import java.sql.ResultSet;
005    import java.sql.ResultSetMetaData;
006    import java.sql.Statement;
007    import java.sql.SQLException;
008    import java.sql.SQLWarning;
009    
010    /**
011     * A decorator around a <code>Statement</code>.  This is used to provide
012     * the default method implementations for the methods in the statement
013     * interface to the sub-classes.
014     *
015     * <p>Copyright 2005 Rakesh Vidyadharan</p>
016     * @author Rakesh Vidyadharan 2005-11-18
017     * @version $Id: ConnectionFactory.java,v 1.2 2005/10/29 22:27:38 rakesh Exp $
018     */
019    abstract class StatementDecorator implements Statement
020    {
021      /**
022       * The abstract method that returns the decorated Statement interface
023       * or its sub-class.
024       */
025      public abstract Statement getStatement();
026    
027      /**
028       * Executes the given SQL statement, which returns a single ResultSet 
029       * object. 
030       *
031       * @param sql An SQL statement to be sent to the database, typically 
032       *   a static SQL SELECT statement 
033       * @return ResultSet A ResultSet object that contains the data 
034       *   produced by the given query; never null 
035       * @throws SQLException If a database access error occurs or the 
036       *   given SQL statement produces anything other than a single 
037       *   ResultSet object
038       */
039      public ResultSet executeQuery(String sql) throws SQLException
040      {
041        return getStatement().executeQuery( sql );
042      }
043    
044      /**
045       * Executes the given SQL statement, which may be an INSERT, UPDATE, 
046       * or DELETE statement or an SQL statement that returns nothing, 
047       * such as an SQL DDL getStatement(). 
048       *
049       * @param sql An SQL INSERT, UPDATE or DELETE statement or an SQL 
050       *   statement that returns nothing 
051       * @return int Either the row count for INSERT, UPDATE or DELETE 
052       *   statements, or 0 for SQL statements that return nothing 
053       * @throws SQLException If a database access error occurs or the 
054       *   given SQL statement produces a ResultSet object
055       */
056      public int executeUpdate(String sql) throws SQLException
057      {
058        return getStatement().executeUpdate( sql );
059      }
060    
061      /**
062       * Releases this Statement object's database and JDBC resources 
063       * immediately instead of waiting for this to happen when it is 
064       * automatically closed. It is generally good practice to release 
065       * resources as soon as you are finished with them to avoid tying up 
066       * database resources. 
067       *
068       * <p>Calling the method close on a Statement object that is already 
069       * closed has no effect.</p>
070       *
071       * <p><b>Note:</b> A Statement object is automatically closed when it 
072       * is garbage collected. When a Statement object is closed, its 
073       * current ResultSet object, if one exists, is also closed.</p>
074       *
075       * @throws SQLException If a database access error occurs
076       */
077      public void close() throws SQLException
078      {
079        getStatement().close();
080      }
081    
082      /**
083       * Retrieves the maximum number of bytes that can be returned for 
084       * character and binary column values in a ResultSet object produced 
085       * by this Statement object. This limit applies only to <code>BINARY, 
086       * VARBINARY, LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR</code> 
087       * columns. If the limit is exceeded, the excess data is silently 
088       * discarded. 
089       *
090       * @see #setMaxFieldSize
091       * @return int The current column size limit for columns storing 
092       *   character and binary values; zero means there is no limit 
093       * @throws SQLException If a database access error occurs
094       */
095      public int getMaxFieldSize() throws SQLException
096      {
097        return getStatement().getMaxFieldSize();
098      }
099    
100      /**
101       * Sets the limit for the maximum number of bytes in a ResultSet 
102       * column storing character or binary values to the given number of 
103       * bytes. This limit applies only to <code>BINARY, VARBINARY, 
104       * LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR</code> fields. If 
105       * the limit is exceeded, the excess data is silently discarded. For 
106       * maximum portability, use values greater than 256. 
107       *
108       * @see #setMaxFieldSize
109       * @param max The new column size limit in bytes; zero means there is 
110       *   no limit 
111       * @throws SQLException If a database access error occurs or the 
112       *   condition <code>max &gt;= 0</code> is not satisfied.
113       */
114      public void setMaxFieldSize(int max) throws SQLException
115      {
116        getStatement().setMaxFieldSize( max );
117      }
118    
119      /**
120       * Retrieves the maximum number of rows that a ResultSet object 
121       * produced by this Statement object can contain. If this limit is 
122       * exceeded, the excess rows are silently dropped. 
123       *
124       * @see #setMaxRows
125       * @return int The current maximum number of rows for a ResultSet 
126       *   object produced by this Statement object; zero means there is 
127       *   no limit 
128       * @throws SQLException If a database access error occurs
129       */
130      public int getMaxRows() throws SQLException
131      {
132        return getStatement().getMaxRows();
133      }
134    
135      /**
136       * Sets the limit for the maximum number of rows that any ResultSet 
137       * object can contain to the given number. If the limit is exceeded, 
138       * the excess rows are silently dropped. 
139       *
140       * @see #getMaxRows
141       * @see #setEscapeProcessing
142       * @param max The new max rows limit; zero means there is no limit 
143       * @throws SQLException If a database access error occurs or the 
144       *   condition <code>max &gt;= 0</code> is not satisfied
145       */
146      public void setMaxRows(int max) throws SQLException
147      {
148        getStatement().setMaxRows( max );
149      }
150    
151      /**
152       * Sets escape processing on or off. If escape scanning is on (the 
153       * default), the driver will do escape substitution before sending 
154       * the SQL statement to the database. Note: Since prepared statements 
155       * have usually been parsed prior to making this call, disabling 
156       * escape processing for PreparedStatements objects will have no 
157       * effect. 
158       *
159       * @param enable <code>true</code> to enable escape processing; 
160       *   <code>false</code> to disable it 
161       * @throws SQLException If a database access error occurs
162       */
163      public void setEscapeProcessing(boolean enable) throws SQLException
164      {
165        getStatement().setEscapeProcessing( enable );
166      }
167    
168      /**
169       * Retrieves the number of seconds the driver will wait for a 
170       * Statement object to execute. If the limit is exceeded, a 
171       * SQLException is thrown. 
172       *
173       * @see #setQueryTimeout
174       * @return int The current query timeout limit in seconds; zero 
175       *   means there is no limit 
176       * @throws SQLException If a database access error occurs
177       */
178      public int getQueryTimeout() throws SQLException
179      {
180        return getStatement().getQueryTimeout();
181      }
182    
183      /**
184       * Sets the number of seconds the driver will wait for a Statement 
185       * object to execute to the given number of seconds. If the limit is 
186       * exceeded, an SQLException is thrown. 
187       *
188       * @see #getQueryTimeout
189       * @param seconds The new query timeout limit in seconds; zero means 
190       *   there is no limit 
191       * @throws SQLException If a database access error occurs or the 
192       *   condition <code>seconds &gt;= 0</code> is not satisfied
193       */
194      public void setQueryTimeout(int seconds) throws SQLException
195      {
196        getStatement().setQueryTimeout( seconds );
197      }
198    
199      /**
200       * Cancels this Statement object if both the DBMS and driver support 
201       * aborting an SQL getStatement().  This method can be used by one thread 
202       * to cancel a statement that is being executed by another thread. 
203       *
204       * @throws SQLException If a database access error occurs
205       */
206      public void cancel() throws SQLException
207      {
208        getStatement().cancel();
209      }
210    
211      /**
212       * Retrieves the first warning reported by calls on this Statement 
213       * object. Subsequent Statement object warnings will be chained to 
214       * this SQLWarning object. 
215       *
216       * <p>The warning chain is automatically cleared each time a 
217       * statement is (re)executed. This method may not be called on a 
218       * closed Statement object; doing so will cause an SQLException to be 
219       * thrown.</p>
220       * 
221       * <p><b>Note:</b> If you are processing a ResultSet object, any 
222       * warnings associated with reads on that ResultSet object will be 
223       * chained on it rather than on the Statement object that produced 
224       * it.</p>
225       *
226       * @return SQLWarning The first SQLWarning object or null if there 
227       *   are no warnings 
228       * @throws SQLException If a database access error occurs or this 
229       *   method is called on a closed statement
230       */
231      public SQLWarning getWarnings() throws SQLException
232      {
233        return getStatement().getWarnings();
234      }
235    
236      /**
237       * Clears all the warnings reported on this Statement object. After 
238       * a call to this method, the method {@link #getWarnings} will return 
239       * <code>null</code> until a new warning is reported for this 
240       * Statement object. 
241       *
242       * @throws SQLException If a database access error occurs
243       */
244      public void clearWarnings() throws SQLException
245      {
246        getStatement().clearWarnings();
247      }
248    
249      /**
250       * Sets the SQL cursor name to the given String, which will be used 
251       * by subsequent Statement object execute methods. This name can then 
252       * be used in SQL positioned update or delete statements to identify 
253       * the current row in the ResultSet object generated by this 
254       * getStatement(). If the database does not support positioned 
255       * update/delete, this method is a noop. To insure that a cursor has 
256       * the proper isolation level to support updates, the cursor's 
257       * SELECT statement should have the form SELECT FOR UPDATE. If FOR 
258       * UPDATE is not present, positioned updates may fail. 
259       *
260       * <p><b>Note:</b> By definition, the execution of positioned updates 
261       * and deletes must be done by a different Statement object than the 
262       * one that generated the ResultSet object being used for positioning.
263       * Also, cursor names must be unique within a connection.</p>
264       *
265       * @param name The new cursor name, which must be unique within a 
266       *   connection 
267       * @throws SQLException If a database access error occurs
268       */
269      public void setCursorName(String name) throws SQLException
270      {
271        getStatement().setCursorName( name );
272      }
273    
274      /**
275       * Executes the given SQL statement, which may return multiple 
276       * results. In some (uncommon) situations, a single SQL statement may 
277       * return multiple result sets and/or update counts. Normally you can 
278       * ignore this unless you are (1) executing a stored procedure that 
279       * you know may return multiple results or (2) you are dynamically 
280       * executing an unknown SQL string. 
281       *
282       * <p>The execute method executes an SQL statement and indicates the 
283       * form of the first result. You must then use the methods 
284       * {@link #getResultSet} or {@link #getUpdateCount} to retrieve the 
285       * result, and {@link #getMoreResults} to move to any subsequent 
286       * result(s).</p>
287       *
288       * @see #getResultSet
289       * @see #getUpdateCount
290       * @see #getMoreResults
291       * @param sql Any SQL statement 
292       * @return boolean <code>true</code> if the first result is a 
293       *   ResultSet object; <code>false</code> if it is an update count or 
294       *   there are no results 
295       * @throws SQLException If a database access error occurs
296       */
297      public boolean execute(String sql) throws SQLException
298      {
299        return getStatement().execute( sql );
300      }
301    
302      /**
303       * Retrieves the current result as a ResultSet object. This method 
304       * should be called only once per result. 
305       *
306       * @see #execute( String )
307       * @see #getUpdateCount
308       * @return ResultSet The current result as a ResultSet object or 
309       *   <code>null</code> if the result is an update count or there are 
310       *   no more results 
311       * @throws SQLException If a database access error occurs
312       */
313      public ResultSet getResultSet() throws SQLException
314      {
315        return getStatement().getResultSet();
316      }
317    
318      /**
319       * Retrieves the current result as an update count; if the result is 
320       * a ResultSet object or there are no more results, -1 is returned. 
321       * This method should be called only once per result. 
322       *
323       * @see #execute
324       * @see #getMoreResults
325       * @return int The current result as an update count; -1 if the 
326       *   current result is a ResultSet object or there are no more 
327       *   results 
328       * @throws SQLException If a database access error occurs
329       */
330      public int getUpdateCount() throws SQLException
331      {
332        return getStatement().getUpdateCount();
333      }
334    
335      /**
336       * Moves to this Statement object's next result, returns <code>true
337       * </code>if it is a ResultSet object, and implicitly closes any 
338       * current ResultSet object(s) obtained with the method getResultSet. 
339       *
340       * <p>There are no more results when the following is true:</p>
341       * <pre> 
342       *   // stmt is a Statement object
343       *   ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
344       * </pre>
345       *
346       * @see #execute
347       * @see #setFetchDirection
348       * @return boolean <code>true</code> if the next result is a 
349       *   ResultSet object; <code>false</code> if it is an update count or 
350       *   there are no more results 
351       * @throws SQLException If a database access error occurs
352       */
353      public boolean getMoreResults() throws SQLException
354      {
355        return getStatement().getMoreResults();
356      }
357    
358      /**
359       * Gives the driver a hint as to the direction in which rows will be 
360       * processed in ResultSet objects created using this Statement object.
361       * The default value is <code>ResultSet.FETCH_FORWARD</code>.
362       *
363       * <p><b>Note</b> that this method sets the default fetch direction 
364       * for result sets generated by this Statement object. Each result 
365       * set has its own methods for getting and setting its own fetch 
366       * direction.</p>
367       *
368       * @see #getFetchDirection
369       * @param direction The initial direction for processing rows 
370       * @throws SQLException If a database access error occurs or the 
371       *   given direction is not one of <code>ResultSet.FETCH_FORWARD</code>, 
372       *   <code>ResultSet.FETCH_REVERSE</code>, or 
373       *   <code>ResultSet.FETCH_UNKNOWN</code>
374       */
375      public void setFetchDirection(int direction) throws SQLException
376      {
377        getStatement().setFetchDirection( direction );
378      }
379    
380      /**
381       * Retrieves the direction for fetching rows from database tables 
382       * that is the default for result sets generated from this Statement 
383       * object. If this Statement object has not set a fetch direction by 
384       * calling the method setFetchDirection, the return value is 
385       * implementation-specific. 
386       *
387       * @see #setFetchDirection
388       * @see #setFetchSize
389       * @return int The default fetch direction for result sets generated 
390       *   from this Statement object 
391       * @throws SQLException If a database access error occurs
392       */
393      public int getFetchDirection() throws SQLException
394      {
395        return getStatement().getFetchDirection();
396      }
397    
398      /**
399       * Gives the JDBC driver a hint as to the number of rows that should 
400       * be fetched from the database when more rows are needed. The number 
401       * of rows specified affects only result sets created using this 
402       * getStatement(). If the value specified is zero, then the hint is 
403       * ignored. The default value is zero. 
404       *
405       * @see #getFetchSize
406       * @param rows The number of rows to fetch 
407       * @throws SQLException If a database access error occurs, or the 
408       *   condition <code>0 &lt;= rows &lt;= this.getMaxRows()</code>
409       *   is not satisfied.
410       */
411      public void setFetchSize(int rows) throws SQLException
412      {
413        getStatement().setFetchSize( rows );
414      }
415    
416      /**
417       * Retrieves the number of result set rows that is the default fetch 
418       * size for ResultSet objects generated from this Statement object. 
419       * If this Statement object has not set a fetch size by calling the 
420       * method {@link #setFetchSize}, the return value is 
421       * implementation-specific. 
422       *
423       * @see #setFetchSize
424       * @return int The default fetch size for result sets generated from 
425       *   this Statement object 
426       * @throws SQLException If a database access error occurs
427       */
428      public int getFetchSize() throws SQLException
429      {
430        return getStatement().getFetchSize();
431      }
432    
433      /**
434       * Retrieves the result set concurrency for ResultSet objects 
435       * generated by this Statement object. 
436       *
437       * @return int Either <code>ResultSet.CONCUR_READ_ONLY</code> or 
438       *   <code>ResultSet.CONCUR_UPDATABLE</code>
439       * @throws SQLException If a database access error occurs
440       */
441      public int getResultSetConcurrency() throws SQLException
442      {
443        return getStatement().getResultSetConcurrency();
444      }
445    
446      /**
447       * Retrieves the result set type for ResultSet objects generated by 
448       * this Statement object. 
449       *
450       * @return int One of <code>ResultSet.TYPE_FORWARD_ONLY</code>, 
451       *   <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or 
452       *   <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
453       * @throws SQLException If a database access error occurs
454       */
455      public int getResultSetType() throws SQLException
456      {
457        return getStatement().getResultSetType();
458      }
459    
460      /**
461       * Adds the given SQL command to the current list of commmands for 
462       * this Statement object. The commands in this list can be executed 
463       * as a batch by calling the method executeBatch. 
464       *
465       * <p><b>NOTE:</b> This method is optional.</p>
466       * 
467       * @see #executeBatch
468       * @see #clearBatch
469       * @param sql Typically this is a static SQL INSERT or UPDATE 
470       *   statement 
471       * @throws SQLException If a database access error occurs, or the 
472       *   driver does not support batch updates
473       */
474      public void addBatch(String sql) throws SQLException
475      {
476        getStatement().addBatch( sql );
477      }
478    
479      /**
480       * Empties this Statement object's current list of SQL commands. 
481       *
482       * <p><b>NOTE:</b> This method is optional.</p>
483       *
484       * @see #addBatch
485       * @throws SQLException If a database access error occurs or the 
486       *   driver does not support batch updates
487       */
488      public void clearBatch() throws SQLException
489      {
490        getStatement().clearBatch();
491      }
492    
493      /**
494       * Submits a batch of commands to the database for execution and if 
495       * all commands execute successfully, returns an array of update 
496       * counts. The int elements of the array that is returned are ordered 
497       * to correspond to the commands in the batch, which are ordered 
498       * according to the order in which they were added to the batch. The 
499       * elements in the array returned by the method executeBatch may be 
500       * one of the following: 
501       *
502       * <ul>
503       *   <li>A number greater than or equal to zero -- indicates that 
504       *   the command was processed successfully and is an update count 
505       *   giving the number of rows in the database that were affected by 
506       *   the command's execution</li>
507       *   <li A value of <code>SUCCESS_NO_INFO</code> -- indicates that 
508       *   the command was processed successfully but that the number of 
509       *   rows affected is unknown</li>
510       * </ul>
511       *
512       * <p>If one of the commands in a batch update fails to execute 
513       * properly, this method throws a <code>BatchUpdateException</code>, 
514       * and a JDBC driver may or may not continue to process the remaining 
515       * commands in the batch. However, the driver's behavior must be 
516       * consistent with a particular DBMS, either always continuing to 
517       * process commands or never continuing to process commands. If the 
518       * driver continues processing after a failure, the array returned by 
519       * the method <code>BatchUpdateException.getUpdateCounts</code> will 
520       * contain as many elements as there are commands in the batch, and 
521       * at least one of the elements will be the following: 
522       *
523       * <ul>
524       *   <li>A value of <code>EXECUTE_FAILED</code> -- indicates that the 
525       *   command failed to execute successfully and occurs only if a 
526       *   driver continues to process commands after a command fails</li>
527       *   <li>A driver is not required to implement this method. The 
528       *   possible implementations and return values have been modified 
529       *   in the Java 2 SDK, Standard Edition, version 1.3 to accommodate 
530       *   the option of continuing to proccess commands in a batch update 
531       *   after a <code>BatchUpdateException</code> obejct has been 
532       *   thrown.</li>
533       * </ul>
534       *
535       * @return int[] An array of update counts containing one element 
536       *   for each command in the batch. The elements of the array are 
537       *   ordered according to the order in which commands were added to 
538       *   the batch. 
539       * @throws SQLException If a database access error occurs or the 
540       *   driver does not support batch statements. Throws 
541       *   <code>BatchUpdateException</code> (a subclass of SQLException) 
542       *   if one of the commands sent to the database fails to execute 
543       *   properly or attempts to return a result set.
544       */
545      public int[] executeBatch() throws SQLException
546      {
547        return getStatement().executeBatch();
548      }
549    
550      /**
551       * Retrieves the Connection object that produced this Statement 
552       * object. 
553       *
554       * @return Connection The connection that produced this statement 
555       * @throws SQLException If a database access error occurs
556       */
557      public Connection getConnection() throws SQLException
558      {
559        return getStatement().getConnection();
560      }
561    
562      /**
563       * Moves to this Statement object's next result, deals with any 
564       * current ResultSet object(s) according to the instructions 
565       * specified by the given flag, and returns true if the next result 
566       * is a ResultSet object. 
567       *
568       * <p>There are no more results when the following is true:</p>
569       * <pre>
570       *   // stmt is a Statement object
571       *   ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
572       * </pre>
573       *
574       * @see #execute
575       * @param current One of the following Statement constants indicating 
576       *   what should happen to current ResultSet objects obtained using 
577       *   the method {@link #getResultSet}: 
578       *   <ul>
579       *   <li><code>Statement.CLOSE_CURRENT_RESULT</code></li>
580       *   <li><code>Statement.KEEP_CURRENT_RESULT</code></li>
581       *   <li><code>Statement.CLOSE_ALL_RESULTS</code></li>
582       *   </ul>
583       * @return boolean <code>true</code> if the next result is a 
584       *   ResultSet object; false if it is an update count or there are 
585       *   no more results 
586       * @throws SQLException If a database access error occurs or the 
587       *   argument supplied is not one of the following: <code>
588       *   Statement.CLOSE_CURRENT_RESULT</code>, <code>
589       *   Statement.KEEP_CURRENT_RESULT</code>, or <code>
590       *   Statement.CLOSE_ALL_RESULTS</code>.
591       */
592      public boolean getMoreResults(int current) throws SQLException
593      {
594        return getStatement().getMoreResults( current );
595      }
596    
597      /**
598       * Retrieves any auto-generated keys created as a result of executing 
599       * this Statement object. If this Statement object did not generate 
600       * any keys, an empty ResultSet object is returned. 
601       *
602       * @return ResultSet A ResultSet object containing the auto-generated 
603       *   key(s) generated by the execution of this Statement object 
604       * @throws SQLException If a database access error occurs
605       */
606      public ResultSet getGeneratedKeys() throws SQLException
607      {
608        return getStatement().getGeneratedKeys();
609      }
610    
611      /**
612       * Executes the given SQL statement and signals the driver with the 
613       * given flag about whether the auto-generated keys produced by this 
614       * Statement object should be made available for retrieval. 
615       *
616       * @param sql Must be an SQL INSERT, UPDATE or DELETE statement or an 
617       *   SQL statement that returns nothing
618       * @param autoGeneratedKeys A flag indicating whether auto-generated 
619       *   keys should be made available for retrieval; one of the 
620       *   following constants: <code>Statement.RETURN_GENERATED_KEYS, 
621       *   Statement.NO_GENERATED_KEYS</code>
622       * @return int Either the row count for INSERT, UPDATE or DELETE 
623       *   statements, or 0 for SQL statements that return nothing 
624       * @throws SQLException If a database access error occurs, the given 
625       *   SQL statement returns a ResultSet object, or the given constant 
626       *   is not one of those allowed
627       */
628      public int executeUpdate(String sql, int autoGeneratedKeys) 
629        throws SQLException
630      {
631        return getStatement().executeUpdate( sql, autoGeneratedKeys );
632      }
633    
634      /**
635       * Executes the given SQL statement and signals the driver that the 
636       * auto-generated keys indicated in the given array should be made 
637       * available for retrieval. The driver will ignore the array if the 
638       * SQL statement is not an INSERT getStatement(). 
639       *
640       * @see #executeUpdate( String, int )
641       * @param sql An SQL INSERT, UPDATE or DELETE statement or an SQL 
642       *   statement that returns nothing, such as an SQL DDL statement
643       * @param columnIndexes An array of column indexes indicating the 
644       *   columns that should be returned from the inserted row 
645       * @return int Either the row count for INSERT, UPDATE, or DELETE 
646       *   statements, or 0 for SQL statements that return nothing
647       * @throws SQLException  If a database access error occurs, the SQL 
648       *   statement returns a ResultSet object, or the second argument 
649       *   supplied to this method is not an int array whose elements are 
650       *   valid column indexes
651       */
652      public int executeUpdate(String sql, int[] columnIndexes) 
653        throws SQLException
654      {
655        return getStatement().executeUpdate( sql, columnIndexes );
656      }
657    
658      /**
659       * Executes the given SQL statement and signals the driver that the 
660       * auto-generated keys indicated in the given array should be made 
661       * available for retrieval. The driver will ignore the array if the 
662       * SQL statement is not an INSERT getStatement(). 
663       *
664       * @param sql An SQL INSERT, UPDATE or DELETE statement or an SQL 
665       *   statement that returns nothing
666       * @param columnNames An array of the names of the columns that 
667       *   should be returned from the inserted row 
668       * @return int Either the row count for INSERT, UPDATE, or DELETE 
669       *   statements, or 0 for SQL statements that return nothing 
670       * @throws SQLException If a database access error occurs, the SQL 
671       *   statement returns a ResultSet object, or the second argument 
672       *   supplied to this method is not a String array whose elements are 
673       *   valid column names
674       */
675      public int executeUpdate(String sql, String[] columnNames) 
676        throws SQLException
677      {
678        return getStatement().executeUpdate( sql, columnNames );
679      }
680    
681      /**
682       * Executes the given SQL statement, which may return multiple 
683       * results, and signals the driver that any auto-generated keys 
684       * should be made available for retrieval. The driver will ignore 
685       * this signal if the SQL statement is not an INSERT getStatement(). 
686       *
687       * <p>In some (uncommon) situations, a single SQL statement may 
688       * return multiple result sets and/or update counts. Normally you can 
689       * ignore this unless you are:
690       * <ol>
691       *   <li>executing a stored procedure that you know may return 
692       *   multiple results or</li>
693       *   <li>dynamically executing an unknown SQL string.</li>
694       * </ol>
695       * </p>
696       *
697       * <p>The execute method executes an SQL statement and indicates the 
698       * form of the first result. You must then use the methods 
699       * {@link #getResultSet} or {@link #getUpdateCount} to retrieve the 
700       * result, and {@link #getMoreResults} to move to any subsequent 
701       * result(s).</p>
702       *
703       * @see #getResultSet
704       * @see #getUpdateCount
705       * @see #getMoreResults
706       * @see #getGeneratedKeys
707       * @param sql Any SQL statement
708       * @param autoGeneratedKeys A constant indicating whether 
709       *   auto-generated keys should be made available for retrieval using 
710       *   the method {@link #getGeneratedKeys}; one of the following 
711       *   constants: <code>Statement.RETURN_GENERATED_KEYS</code> or 
712       *   <code>Statement.NO_GENERATED_KEYS</code>
713       * @return boolean <code>true</code> if the first result is a 
714       *   ResultSet object; false if it is an update count or there are 
715       *   no results 
716       * @throws SQLException If a database access error occurs or the 
717       *   second parameter supplied to this method is not <code>
718       *   Statement.RETURN_GENERATED_KEYS</code> or <code>
719       *   Statement.NO_GENERATED_KEYS</code>.
720       */
721      public boolean execute(String sql, int autoGeneratedKeys)
722        throws SQLException
723      {
724        return getStatement().execute( sql, autoGeneratedKeys );
725      }
726    
727      /**
728       * Executes the given SQL statement, which may return multiple 
729       * results, and signals the driver that the auto-generated keys 
730       * indicated in the given array should be made available for 
731       * retrieval. This array contains the indexes of the columns in the 
732       * target table that contain the auto-generated keys that should be 
733       * made available. The driver will ignore the array if the given SQL 
734       * statement is not an INSERT getStatement(). 
735       *
736       * <p>Under some (uncommon) situations, a single SQL statement may 
737       * return multiple result sets and/or update counts. Normally you can 
738       * ignore this unless you are (1) executing a stored procedure that 
739       * you know may return multiple results or (2) you are dynamically 
740       * executing an unknown SQL string.</p>
741       *
742       * <p>The execute method executes an SQL statement and indicates the 
743       * form of the first result. You must then use the methods 
744       * {@link #getResultSet} or {@link #getUpdateCount} to retrieve the 
745       * result, and {@link #getMoreResults} to move to any subsequent 
746       * result(s).</p>
747       *
748       * @param sql Any SQL statement
749       * @param columnIndexes An array of the indexes of the columns in the 
750       *   inserted row that should be made available for retrieval by a 
751       *     call to the method getGeneratedKeys 
752       * @return boolean <code>true</code> if the first result is a 
753       *   ResultSet object; <code>false</code> if it is an update count or 
754       *   there are no results 
755       * @throws SQLException If a database access error occurs or the 
756       *   elements in the int array passed to this method are not valid 
757       *     column indexes
758       */
759      public boolean execute(String sql, int[] columnIndexes) 
760        throws SQLException
761      {
762        return getStatement().execute( sql, columnIndexes );
763      }
764    
765      /**
766       * Executes the given SQL statement, which may return multiple 
767       * results, and signals the driver that the auto-generated keys 
768       * indicated in the given array should be made available for 
769       * retrieval. This array contains the names of the columns in the 
770       * target table that contain the auto-generated keys that should be 
771       * made available. The driver will ignore the array if the given SQL 
772       * statement is not an INSERT getStatement(). 
773       *
774       * <p>In some (uncommon) situations, a single SQL statement may 
775       * return multiple result sets and/or update counts. Normally you 
776       * can ignore this unless you are (1) executing a stored procedure 
777       * that you know may return multiple results or (2) you are 
778       * dynamically executing an unknown SQL string.</p>
779       *
780       * <p>The execute method executes an SQL statement and indicates the 
781       * form of the first result. You must then use the methods 
782       * {@link #getResultSet} or {@link #getUpdateCount} to retrieve the 
783       * result, and {@link #getMoreResults} to move to any subsequent 
784       * result(s).</p>
785       *
786       * @see #getResultSet
787       * @see #getUpdateCount
788       * @see #getMoreResults
789       * @see #getGeneratedKeys
790       * @param sql Any SQL statement
791       * @param columnNames An array of the names of the columns in the 
792       *   inserted row that should be made available for retrieval by a 
793       *     call to the method getGeneratedKeys 
794       * @return boolean <code>true</code> if the next result is a 
795       *   ResultSet object; <code>false</code> if it is an update count or 
796       *   there are no more results 
797       * @throws SQLException If a database access error occurs or the 
798       *   elements of the String array passed to this method are not valid 
799       *   column names
800       */
801      public boolean execute(String sql, String[] columnNames)
802        throws SQLException
803      {
804        return getStatement().execute( sql, columnNames );
805      }
806    
807      /**
808       * Retrieves the result set holdability for ResultSet objects 
809       * generated by this Statement object. 
810       *
811       * @return int Either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> 
812       *   or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
813       * @throws SQLException If a database access error occurs
814       */
815      public int getResultSetHoldability() throws SQLException
816      {
817        return getStatement().getResultSetHoldability();
818      }
819    }