View Javadoc

1   /*
2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    * 1. Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    * 2. Redistributions in binary form must reproduce the above copyright notice,
10   *    this list of conditions and the following disclaimer in the documentation
11   *    and/or other materials provided with the distribution.
12   * 3. The end-user documentation included with the redistribution, if any, must
13   *    include the following acknowledgment:
14   *
15   *       "This product includes software developed by Gargoyle Software Inc.
16   *        (http://www.GargoyleSoftware.com/)."
17   *
18   *    Alternately, this acknowledgment may appear in the software itself, if
19   *    and wherever such third-party acknowledgments normally appear.
20   * 4. The name "Gargoyle Software" must not be used to endorse or promote
21   *    products derived from this software without prior written permission.
22   *    For written permission, please contact info@GargoyleSoftware.com.
23   * 5. Products derived from this software may not be called "GSBase", nor may
24   *    "GSBase" appear in their name, without prior written permission of
25   *    Gargoyle Software Inc.
26   *
27   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30   * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   */
38  package com.gargoylesoftware.base.resource.jdbc;
39  
40  import java.sql.Connection;
41  import java.sql.ResultSet;
42  import java.sql.SQLException;
43  import java.sql.SQLWarning;
44  import java.sql.Statement;
45  import java.util.ArrayList;
46  import java.util.Iterator;
47  import java.util.List;
48  
49  /***
50   *  <P>
51   *
52   *  The object used for executing a static SQL statement and obtaining the
53   *  results produced by it. <P>
54   *
55   *  Only one <code>ResultSet</code> object per <code>Statement</code> object can
56   *  be open at any point in time. Therefore, if the reading of one <code>ResultSet</code>
57   *  object is interleaved with the reading of another, each must have been
58   *  generated by different <code>Statement</code> objects. All statement <code>execute</code>
59   *  methods implicitly close a statment's current <code>ResultSet</code> object
60   *  if an open one exists.
61   *
62   * @version  $Revision: 1.5 $
63   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
64   */
65  public class StatementWrapper implements Statement {
66  
67      private Statement delegate_;
68      private Connection connection_;
69  
70      private boolean isOpen_ = true;
71      private final List openResultSets_ = new ArrayList();
72  
73  
74      /***
75       *  Create a new wrapper
76       *
77       * @param  statement The statement that we are wrapping
78       */
79      public StatementWrapper( final Statement statement ) {
80          if( statement == null ) {
81              throw new NullPointerException( "statement" );
82          }
83  
84          delegate_ = statement;
85      }
86  
87  
88      /***
89       *  Set the connection that created this statement
90       *
91       * @param  connection The connection
92       */
93      public final void setConnection( final Connection connection ) {
94          if( connection == null ) {
95              throw new NullPointerException();
96          }
97          connection_ = connection;
98      }
99  
100 
101     /***
102      *  Sets the limit for the maximum number of bytes in a column to the given
103      *  number of bytes. This is the maximum number of bytes that can be
104      *  returned for any column value. This limit applies only to <code>BINARY</code>
105      *  , <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
106      *  <code>VARCHAR</code>, and <code>LONGVARCHAR</code> fields. If the limit
107      *  is exceeded, the excess data is silently discarded. For maximum
108      *  portability, use values greater than 256.
109      *
110      * @param  max the new max column size limit; zero means unlimited
111      * @exception  SQLException if a database access error occurs
112      */
113     public final void setMaxFieldSize( int max )
114         throws SQLException {
115         checkIsOpen();
116         delegate_.setMaxFieldSize( max );
117     }
118 
119 
120     /***
121      *  Sets the limit for the maximum number of rows that any <code>ResultSet</code>
122      *  object can contain to the given number. If the limit is exceeded, the
123      *  excess rows are silently dropped.
124      *
125      * @param  max the new max rows limit; zero means unlimited
126      * @exception  SQLException if a database access error occurs
127      */
128     public final void setMaxRows( int max )
129         throws SQLException {
130         checkIsOpen();
131         delegate_.setMaxRows( max );
132     }
133 
134 
135     /***
136      *  Sets escape processing on or off. If escape scanning is on (the
137      *  default), the driver will do escape substitution before sending the SQL
138      *  to the database. Note: Since prepared statements have usually been
139      *  parsed prior to making this call, disabling escape processing for
140      *  prepared statements will have no effect.
141      *
142      * @param  enable <code>true</code> to enable; <code>false</code> to disable
143      * @exception  SQLException if a database access error occurs
144      */
145     public final void setEscapeProcessing( boolean enable )
146         throws SQLException {
147         checkIsOpen();
148         delegate_.setEscapeProcessing( enable );
149     }
150 
151 
152     /***
153      *  Sets the number of seconds the driver will wait for a <code>Statement</code>
154      *  object to execute to the given number of seconds. If the limit is
155      *  exceeded, an <code>SQLException</code> is thrown.
156      *
157      * @param  seconds the new query timeout limit in seconds; zero means
158      *      unlimited
159      * @exception  SQLException if a database access error occurs
160      */
161     public final void setQueryTimeout( int seconds )
162         throws SQLException {
163         checkIsOpen();
164         delegate_.setQueryTimeout( seconds );
165     }
166 
167 
168     /***
169      *  Defines the SQL cursor name that will be used by subsequent <code>Statement</code>
170      *  object <code>execute</code> methods. This name can then be used in SQL
171      *  positioned update/delete statements to identify the current row in the
172      *  <code>ResultSet</code> object generated by this statement. If the
173      *  database doesn't support positioned update/delete, this method is a
174      *  noop. To insure that a cursor has the proper isolation level to support
175      *  updates, the cursor's <code>SELECT</code> statement should be of the
176      *  form 'select for update ...'. If the 'for update' phrase is omitted,
177      *  positioned updates may fail. <P>
178      *
179      *  <B>Note:</B> By definition, positioned update/delete execution must be
180      *  done by a different <code>Statement</code> object than the one which
181      *  generated the <code>ResultSet</code> object being used for positioning.
182      *  Also, cursor names must be unique within a connection.
183      *
184      * @param  name the new cursor name, which must be unique within a
185      *      connection
186      * @exception  SQLException if a database access error occurs
187      */
188     public final void setCursorName( String name )
189         throws SQLException {
190         checkIsOpen();
191         delegate_.setCursorName( name );
192     }
193 
194 
195     //--------------------------JDBC 2.0-----------------------------
196 
197 
198     /***
199      *  Gives the driver a hint as to the direction in which the rows in a
200      *  result set will be processed. The hint applies only to result sets
201      *  created using this <code>Statement</code> object. The default value is
202      *  <code>ResultSet.FETCH_FORWARD</code>. <p>
203      *
204      *  Note that this method sets the default fetch direction for result sets
205      *  generated by this <code>Statement</code> object. Each result set has its
206      *  own methods for getting and setting its own fetch direction.
207      *
208      * @param  direction the initial direction for processing rows
209      * @exception  SQLException if a database access error occurs or the given
210      *      direction is not one of <code>ResultSet.FETCH_FORWARD</code>, <code>ResultSet.FETCH_REVERSE</code>
211      *      , or <code>ResultSet.FETCH_UNKNOWN</code>
212      * @since  1.2
213      */
214     public final void setFetchDirection( int direction )
215         throws SQLException {
216         checkIsOpen();
217         delegate_.setFetchDirection( direction );
218     }
219 
220 
221     /***
222      *  Gives the JDBC driver a hint as to the number of rows that should be
223      *  fetched from the database when more rows are needed. The number of rows
224      *  specified affects only result sets created using this statement. If the
225      *  value specified is zero, then the hint is ignored. The default value is
226      *  zero.
227      *
228      * @param  rows the number of rows to fetch
229      * @exception  SQLException if a database access error occurs, or the
230      *      condition 0 <= rows <= this.getMaxRows() is not satisfied.
231      * @since  1.2
232      */
233     public final void setFetchSize( int rows )
234         throws SQLException {
235         checkIsOpen();
236         delegate_.setFetchSize( rows );
237     }
238 
239 
240     /***
241      *  Return the statement that is wrapped
242      *
243      * @return  The wrapped statement
244      */
245     public final Statement getDelegate() {
246         return delegate_;
247     }
248 
249 
250     /***
251      *  Return true if this statement has been closed
252      *
253      * @return  true if this statement has been closed
254      */
255     public final boolean isClosed() {
256         return isOpen_ == false;
257     }
258 
259     //----------------------------------------------------------------------
260 
261     /***
262      *  Returns the maximum number of bytes allowed for any column value. This
263      *  limit is the maximum number of bytes that can be returned for any column
264      *  value. The limit applies only to <code>BINARY</code>, <code>VARBINARY</code>
265      *  , <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
266      *  and <code>LONGVARCHAR</code> columns. If the limit is exceeded, the
267      *  excess data is silently discarded.
268      *
269      * @return  the current max column size limit; zero means unlimited
270      * @exception  SQLException if a database access error occurs
271      */
272     public final int getMaxFieldSize()
273         throws SQLException {
274         checkIsOpen();
275         return delegate_.getMaxFieldSize();
276     }
277 
278 
279     /***
280      *  Retrieves the maximum number of rows that a <code>ResultSet</code>
281      *  object can contain. If the limit is exceeded, the excess rows are
282      *  silently dropped.
283      *
284      * @return  the current max row limit; zero means unlimited
285      * @exception  SQLException if a database access error occurs
286      */
287     public final int getMaxRows()
288         throws SQLException {
289         checkIsOpen();
290         return delegate_.getMaxRows();
291     }
292 
293 
294     /***
295      *  Retrieves the number of seconds the driver will wait for a <code>Statement</code>
296      *  object to execute. If the limit is exceeded, a <code>SQLException</code>
297      *  is thrown.
298      *
299      * @return  the current query timeout limit in seconds; zero means unlimited
300      * @exception  SQLException if a database access error occurs
301      */
302     public final int getQueryTimeout()
303         throws SQLException {
304         checkIsOpen();
305         return delegate_.getQueryTimeout();
306     }
307 
308 
309     /***
310      *  Retrieves the first warning reported by calls on this <code>Statement</code>
311      *  object. Subsequent <code>Statement</code> object warnings will be
312      *  chained to this <code>SQLWarning</code> object. <p>
313      *
314      *  The warning chain is automatically cleared each time a statement is
315      *  (re)executed. <P>
316      *
317      *  <B>Note:</B> If you are processing a <code>ResultSet</code> object, any
318      *  warnings associated with reads on that <code>ResultSet</code> object
319      *  will be chained on it.
320      *
321      * @return  the first <code>SQLWarning</code> object or <code>null</code>
322      * @exception  SQLException if a database access error occurs
323      */
324     public final SQLWarning getWarnings()
325         throws SQLException {
326         checkIsOpen();
327         return delegate_.getWarnings();
328     }
329 
330 
331     /***
332      *  Returns the current result as a <code>ResultSet</code> object. This
333      *  method should be called only once per result.
334      *
335      * @return  the current result as a <code>ResultSet</code> object; <code>null</code>
336      *      if the result is an update count or there are no more results
337      * @exception  SQLException if a database access error occurs
338      */
339     public final ResultSet getResultSet()
340         throws SQLException {
341         checkIsOpen();
342         return wrapResultSet( delegate_.getResultSet() );
343     }
344 
345 
346     /***
347      *  Returns the current result as an update count; if the result is a <code>ResultSet</code>
348      *  object or there are no more results, -1 is returned. This method should
349      *  be called only once per result.
350      *
351      * @return  the current result as an update count; -1 if the current result
352      *      is a <code>ResultSet</code> object or there are no more results
353      * @exception  SQLException if a database access error occurs
354      */
355     public final int getUpdateCount()
356         throws SQLException {
357         checkIsOpen();
358         return delegate_.getUpdateCount();
359     }
360 
361 
362     /***
363      *  Moves to a <code>Statement</code> object's next result. It returns
364      *  <code>true</code> if this result is a <code>ResultSet</code> object.
365      *  This method also implicitly closes any current <code>ResultSet</code>
366      *  object obtained with the method <code>getResultSet</code>. <P>
367      *
368      *  There are no more results when the following is true: <PRE>
369      *      <code>(!getMoreResults() && (getUpdateCount() == -1)</code> </PRE>
370      *
371      * @return  <code>true</code> if the next result is a <code>ResultSet</code>
372      *      object; <code>false</code> if it is an update count or there are no
373      *      more results
374      * @exception  SQLException if a database access error occurs
375      */
376     public final boolean getMoreResults()
377         throws SQLException {
378         checkIsOpen();
379         return delegate_.getMoreResults();
380     }
381 
382 
383     /***
384      *  Retrieves the direction for fetching rows from database tables that is
385      *  the default for result sets generated from this <code>Statement</code>
386      *  object. If this <code>Statement</code> object has not set a fetch
387      *  direction by calling the method <code>setFetchDirection</code>, the
388      *  return value is implementation-specific.
389      *
390      * @return  the default fetch direction for result sets generated from this
391      *      <code>Statement</code> object
392      * @exception  SQLException if a database access error occurs
393      * @since  1.2
394      */
395     public final int getFetchDirection()
396         throws SQLException {
397         checkIsOpen();
398         return delegate_.getFetchDirection();
399     }
400 
401 
402     /***
403      *  Retrieves the number of result set rows that is the default fetch size
404      *  for result sets generated from this <code>Statement</code> object. If
405      *  this <code>Statement</code> object has not set a fetch size by calling
406      *  the method <code>setFetchSize</code>, the return value is
407      *  implementation-specific.
408      *
409      * @return  the default fetch size for result sets generated from this
410      *      <code>Statement</code> object
411      * @exception  SQLException if a database access error occurs
412      * @since  1.2
413      */
414     public final int getFetchSize()
415         throws SQLException {
416         checkIsOpen();
417         return delegate_.getFetchSize();
418     }
419 
420 
421     /***
422      *  Retrieves the result set concurrency for <code>ResultSet</code> objects
423      *  generated by this <code>Statement</code> object.
424      *
425      * @return  either <code>ResultSet.CONCUR_READ_ONLY</code> or <code>ResultSet.CONCUR_UPDATABLE</code>
426      * @exception  SQLException If an error occurs
427      * @since  1.2
428      */
429     public final int getResultSetConcurrency()
430         throws SQLException {
431         checkIsOpen();
432         return delegate_.getResultSetConcurrency();
433     }
434 
435 
436     /***
437      *  Retrieves the result set type for <code>ResultSet</code> objects
438      *  generated by this <code>Statement</code> object.
439      *
440      * @return  one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>
441      *      , or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
442      * @exception  SQLException If an error occurs
443      * @since  1.2
444      */
445     public final int getResultSetType()
446         throws SQLException {
447         checkIsOpen();
448         return delegate_.getResultSetType();
449     }
450 
451 
452     /***
453      *  Returns the <code>Connection</code> object that produced this <code>Statement</code>
454      *  object.
455      *
456      * @return  the connection that produced this statement
457      * @exception  SQLException if a database access error occurs
458      * @since  1.2
459      */
460     public final Connection getConnection()
461         throws SQLException {
462         checkIsOpen();
463         return connection_;
464     }
465 
466 
467     /***
468      *  Executes an SQL statement that returns a single <code>ResultSet</code>
469      *  object.
470      *
471      * @param  sql typically this is a static SQL <code>SELECT</code> statement
472      * @return  a <code>ResultSet</code> object that contains the data produced
473      *      by the given query; never <code>null</code>
474      * @exception  SQLException if a database access error occurs
475      */
476     public final ResultSet executeQuery( String sql )
477         throws SQLException {
478         checkIsOpen();
479         return wrapResultSet( delegate_.executeQuery( sql ) );
480     }
481 
482 
483     /***
484      *  Executes an SQL <code>INSERT</code>, <code>UPDATE</code> or <code>DELETE</code>
485      *  statement. In addition, SQL statements that return nothing, such as SQL
486      *  DDL statements, can be executed.
487      *
488      * @param  sql an SQL <code>INSERT</code>, <code>UPDATE</code> or <code>DELETE</code>
489      *      statement or an SQL statement that returns nothing
490      * @return  either the row count for <code>INSERT</code>, <code>UPDATE</code>
491      *      or <code>DELETE</code> statements, or 0 for SQL statements that
492      *      return nothing
493      * @exception  SQLException if a database access error occurs
494      */
495     public final int executeUpdate( String sql )
496         throws SQLException {
497         checkIsOpen();
498         return delegate_.executeUpdate( sql );
499     }
500 
501 
502     /***
503      *  Releases this <code>Statement</code> object's database and JDBC
504      *  resources immediately instead of waiting for this to happen when it is
505      *  automatically closed. It is generally good practice to release resources
506      *  as soon as you are finished with them to avoid tying up database
507      *  resources. <P>
508      *
509      *  <B>Note:</B> A <code>Statement</code> object is automatically closed
510      *  when it is garbage collected. When a <code>Statement</code> object is
511      *  closed, its current <code>ResultSet</code> object, if one exists, is
512      *  also closed.
513      *
514      * @exception  SQLException if a database access error occurs
515      */
516     public final void close()
517         throws SQLException {
518         if( isOpen_ ) {
519             ResultSetWrapper resultSetWrapper;
520             final Iterator iterator = openResultSets_.iterator();
521             while( iterator.hasNext() ) {
522                 resultSetWrapper = (ResultSetWrapper)iterator.next();
523                 if( resultSetWrapper.isClosed() == false ) {
524                     resultSetWrapper.close();
525                 }
526             }
527             openResultSets_.clear();
528 
529             delegate_.close();
530             delegate_ = null;
531         }
532         else {
533             throw new AlreadyClosedException( "Statement is closed" );
534         }
535         isOpen_ = false;
536     }
537 
538 
539     /***
540      *  Cancels this <code>Statement</code> object if both the DBMS and driver
541      *  support aborting an SQL statement. This method can be used by one thread
542      *  to cancel a statement that is being executed by another thread.
543      *
544      * @exception  SQLException if a database access error occurs
545      */
546     public final void cancel()
547         throws SQLException {
548         checkIsOpen();
549         delegate_.cancel();
550     }
551 
552 
553     /***
554      *  Clears all the warnings reported on this <code>Statement</code> object.
555      *  After a call to this method, the method <code>getWarnings</code> will
556      *  return <code>null</code> until a new warning is reported for this <code>Statement</code>
557      *  object.
558      *
559      * @exception  SQLException if a database access error occurs
560      */
561     public final void clearWarnings()
562         throws SQLException {
563         checkIsOpen();
564         delegate_.clearWarnings();
565     }
566 
567     //----------------------- Multiple Results --------------------------
568 
569     /***
570      *  Executes an SQL statement that may return multiple results. Under some
571      *  (uncommon) situations a single SQL statement may return multiple result
572      *  sets and/or update counts. Normally you can ignore this unless you are
573      *  (1) executing a stored procedure that you know may return multiple
574      *  results or (2) you are dynamically executing an unknown SQL string. The
575      *  methods <code>execute</code>, <code>getMoreResults</code>, <code>getResultSet</code>
576      *  , and <code>getUpdateCount</code> let you navigate through multiple
577      *  results. The <code>execute</code> method executes an SQL statement and
578      *  indicates the form of the first result. You can then use the methods
579      *  <code>getResultSet</code> or <code>getUpdateCount</code> to retrieve the
580      *  result, and <code>getMoreResults</code> to move to any subsequent
581      *  result(s).
582      *
583      * @param  sql any SQL statement
584      * @return  <code>true</code> if the next result is a <code>ResultSet</code>
585      *      object; <code>false</code> if it is an update count or there are no
586      *      more results
587      * @exception  SQLException if a database access error occurs
588      */
589     public final boolean execute( String sql )
590         throws SQLException {
591         checkIsOpen();
592         return delegate_.execute( sql );
593     }
594 
595 
596     /***
597      *  Adds an SQL command to the current batch of commmands for this <code>Statement</code>
598      *  object. This method is optional.
599      *
600      * @param  sql typically this is a static SQL <code>INSERT</code> or <code>UPDATE</code>
601      *      statement
602      * @exception  SQLException if a database access error occurs, or the driver
603      *      does not support batch statements
604      * @since  1.2
605      */
606     public final void addBatch( String sql )
607         throws SQLException {
608         checkIsOpen();
609         delegate_.addBatch( sql );
610     }
611 
612 
613     /***
614      *  Makes the set of commands in the current batch empty. This method is
615      *  optional.
616      *
617      * @exception  SQLException if a database access error occurs or the driver
618      *      does not support batch statements
619      * @since  1.2
620      */
621     public final void clearBatch()
622         throws SQLException {
623         checkIsOpen();
624         delegate_.clearBatch();
625     }
626 
627 
628     /***
629      *  Submits a batch of commands to the database for execution and if all
630      *  commands execute successfully, returns an array of update counts. The
631      *  <code>int</code> elements of the array that is returned are ordered to
632      *  correspond to the commands in the batch, which are ordered according to
633      *  the order in which they were added to the batch. The elements in the
634      *  array returned by the method <code>executeBatch</code> may be one of the
635      *  following:
636      *  <OL>
637      *    <LI> A number greater than or equal to zero -- indicates that the
638      *    command was processed successfully and is an update count giving the
639      *    number of rows in the database that were affected by the command's
640      *    execution
641      *    <LI> A value of <code>-2</code> -- indicates that the command was
642      *    processed successfully but that the number of rows affected is unknown
643      *    <P>
644      *
645      *    If one of the commands in a batch update fails to execute properly,
646      *    this method throws a <code>BatchUpdateException</code>, and a JDBC
647      *    driver may or may not continue to process the remaining commands in
648      *    the batch. However, the driver's behavior must be consistent with a
649      *    particular DBMS, either always continuing to process commands or never
650      *    continuing to process commands. If the driver continues processing
651      *    after a failure, the array returned by the method <code>BatchUpdateException.getUpdateCounts</code>
652      *    will contain as many elements as there are commands in the batch, and
653      *    at least one of the elements will be the following: <P>
654      *
655      *
656      *    <LI> A value of <code>-3</code> -- indicates that the command failed
657      *    to execute successfully and occurs only if a driver continues to
658      *    process commands after a command fails
659      *  </OL>
660      *  <P>
661      *
662      *  A driver is not required to implement this method. The possible
663      *  implementations and return values have been modified in the Java 2 SDK,
664      *  Standard Edition, version 1.3 to accommodate the option of continuing to
665      *  proccess commands in a batch update after a <code>BatchUpdateException</code>
666      *  object has been thrown.
667      *
668      * @return  an array of update counts containing one element for each
669      *      command in the batch. The elements of the array are ordered
670      *      according to the order in which commands were added to the batch.
671      * @exception  SQLException if a database access error occurs or the driver
672      *      does not support batch statements. Throws BatchUpdateException (a
673      *      subclass of <code>SQLException</code>) if one of the commands sent
674      *      to the database fails to execute properly or attempts to return a
675      *      result set.
676      * @since  1.3
677      */
678     public final int[] executeBatch()
679         throws SQLException {
680         checkIsOpen();
681         return delegate_.executeBatch();
682     }
683 
684 
685     /***
686      *  Check to see if the connection is still open
687      *
688      * @exception  SQLException If an error occurs
689      */
690     protected final void checkIsOpen()
691         throws SQLException {
692         if( isOpen_ == false ) {
693             throw new SQLException( "Statement is closed" );
694         }
695     }
696 
697 
698     /***
699      *  Wrap the specified result set in a ResultSetWrapper object and return
700      *  the wrapper.
701      *
702      * @param  resultSet The object to be wrapped
703      * @return  The wrapper.
704      */
705     protected final ResultSet wrapResultSet( final ResultSet resultSet ) {
706         final ResultSetWrapper wrapper = new ResultSetWrapper( resultSet );
707         openResultSets_.add( wrapper );
708         return wrapper;
709     }
710 
711     // ===============================================================
712     // =====  NEW FOR 1.4 =============
713 
714     /***
715      * Moves to this <code>Statement</code> object's next result, deals with
716      * any current <code>ResultSet</code> object(s) according  to the instructions
717      * specified by the given flag, and returns
718      * <code>true</code> if the next result is a <code>ResultSet</code> object.
719      *
720      * <P>There are no more results when the following is true:
721      * <PRE>
722      *      <code>(!getMoreResults() && (getUpdateCount() == -1)</code>
723      * </PRE>
724      *
725      * @param current one of the following <code>Statement</code>
726      *        constants indicating what should happen to current
727      *        <code>ResultSet</code> objects obtained using the method
728      *        <code>getResultSet</code:
729      *        <code>CLOSE_CURRENT_RESULT</code>,
730      *        <code>KEEP_CURRENT_RESULT</code>, or
731      *        <code>CLOSE_ALL_RESULTS</code>
732      * @return <code>true</code> if the next result is a <code>ResultSet</code>
733      *         object; <code>false</code> if it is an update count or there are no
734      *         more results
735      * @exception SQLException if a database access error occurs
736      * @since 1.4
737      */
738     public boolean getMoreResults(int current) throws SQLException {
739         checkIsOpen();
740         return delegate_.getMoreResults(current);
741     }
742 
743 
744     /***
745      * Retrieves any auto-generated keys created as a result of executing this
746      * <code>Statement</code> object. If this <code>Statement</code> object did
747      * not generate any keys, an empty <code>ResultSet</code>
748      * object is returned.
749      *
750      * @return a <code>ResultSet</code> object containing the auto-generated key(s)
751      *         generated by the execution of this <code>Statement</code> object
752      * @exception SQLException if a database access error occurs
753      * @since java 1.4
754      */
755     public ResultSet getGeneratedKeys() throws SQLException {
756         checkIsOpen();
757         return delegate_.getGeneratedKeys();
758     }
759 
760 
761     /***
762      * Executes the given SQL statement and signals the driver with the
763      * given flag about whether the
764      * auto-generated keys produced by this <code>Statement</code> object
765      * should be made available for retrieval.
766      *
767      * @param sql must be an SQL <code>INSERT</code>, <code>UPDATE</code> or
768      *        <code>DELETE</code> statement or an SQL statement that
769      *        returns nothing
770      * @param autoGeneratedKeys a flag indicating whether auto-generated keys
771      *        should be made available for retrieval;
772      *         one of the following constants:
773      *         <code>Statement.RETURN_GENERATED_KEYS</code>
774      *         <code>Statement.NO_GENERATED_KEYS</code>
775      * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>
776      *         or <code>DELETE</code> statements, or <code>0</code> for SQL
777      *         statements that return nothing
778      * @exception SQLException if a database access error occurs, the given
779      *            SQL statement returns a <code>ResultSet</code> object, or
780      *            the given constant is not one of those allowed
781      * @since java 1.4
782      */
783     public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
784         checkIsOpen();
785         return delegate_.executeUpdate(sql, autoGeneratedKeys);
786     }
787 
788 
789     /***
790      * Executes the given SQL statement and signals the driver that the
791      * auto-generated keys indicated in the given array should be made available
792      * for retrieval.  The driver will ignore the array if the SQL statement
793      * is not an <code>INSERT</code> statement.
794      *
795      * @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
796      *        <code>DELETE</code> statement or an SQL statement that returns nothing,
797      *        such as an SQL DDL statement
798      * @param columnIndexes an array of column indexes indicating the columns
799      *        that should be returned from the inserted row
800      * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>,
801      *         or <code>DELETE</code> statements, or 0 for SQL statements
802      *         that return nothing
803      * @exception SQLException if a database access error occurs or the SQL
804      *            statement returns a <code>ResultSet</code> object
805      * @since java 1.4
806      */
807     public int executeUpdate(String sql, int columnIndexes[]) throws SQLException {
808         checkIsOpen();
809         return delegate_.executeUpdate(sql, columnIndexes);
810     }
811 
812 
813     /***
814      * Executes the given SQL statement and signals the driver that the
815      * auto-generated keys indicated in the given array should be made available
816      * for retrieval.  The driver will ignore the array if the SQL statement
817      * is not an <code>INSERT</code> statement.
818      *
819      * @param sql an SQL <code>INSERT</code>, <code>UPDATE</code> or
820      *        <code>DELETE</code> statement or an SQL statement that returns nothing
821      * @param columnNames an array of the names of the columns that should be
822      *        returned from the inserted row
823      * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>,
824      *         or <code>DELETE</code> statements, or 0 for SQL statements
825      *         that return nothing
826      * @exception SQLException if a database access error occurs
827      *
828      * @since java 1.4
829      */
830     public int executeUpdate(String sql, String columnNames[]) throws SQLException {
831         checkIsOpen();
832         return delegate_.executeUpdate(sql, columnNames);
833     }
834 
835 
836     /***
837      * Executes the given SQL statement, which may return multiple results,
838      * and signals the driver that any
839      * auto-generated keys should be made available
840      * for retrieval.  The driver will ignore this signal if the SQL statement
841      * is not an <code>INSERT</code> statement.
842      * <P>
843      * In some (uncommon) situations, a single SQL statement may return
844      * multiple result sets and/or update counts.  Normally you can ignore
845      * this unless you are (1) executing a stored procedure that you know may
846      * return multiple results or (2) you are dynamically executing an
847      * unknown SQL string.
848      * <P>
849      * The <code>execute</code> method executes an SQL statement and indicates the
850      * form of the first result.  You must then use the methods
851      * <code>getResultSet</code> or <code>getUpdateCount</code>
852      * to retrieve the result, and <code>getMoreResults</code> to
853      * move to any subsequent result(s).
854      *
855      * @param sql any SQL statement
856      * @param autoGeneratedKeys a constant indicating whether auto-generated
857      *        keys should be made available for retrieval using the method
858      *        <code>getGeneratedKeys</code>; one of the following constants:
859      *        <code>Statement.RETURN_GENERATED_KEYS</code> or
860      *        <code>Statement.NO_GENERATED_KEYS</code>
861      * @return <code>true</code> if the first result is a <code>ResultSet</code>
862      *         object; <code>false</code> if it is an update count or there are
863      *         no results
864      * @exception SQLException if a database access error occurs
865      *
866      * @since java 1.4
867      */
868     public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
869         checkIsOpen();
870         return delegate_.execute(sql, autoGeneratedKeys);
871     }
872 
873 
874     /***
875      * Executes the given SQL statement, which may return multiple results,
876      * and signals the driver that the
877      * auto-generated keys indicated in the given array should be made available
878      * for retrieval.  This array contains the indexes of the columns in the
879      * target table that contain the auto-generated keys that should be made
880      * available. The driver will ignore the array if the given SQL statement
881      * is not an <code>INSERT</code> statement.
882      * <P>
883      * Under some (uncommon) situations, a single SQL statement may return
884      * multiple result sets and/or update counts.  Normally you can ignore
885      * this unless you are (1) executing a stored procedure that you know may
886      * return multiple results or (2) you are dynamically executing an
887      * unknown SQL string.
888      * <P>
889      * The <code>execute</code> method executes an SQL statement and indicates the
890      * form of the first result.  You must then use the methods
891      * <code>getResultSet</code> or <code>getUpdateCount</code>
892      * to retrieve the result, and <code>getMoreResults</code> to
893      * move to any subsequent result(s).
894      *
895      * @param sql any SQL statement
896      * @param columnIndexes an array of the indexes of the columns in the
897      *        inserted row that should be  made available for retrieval by a
898      *        call to the method <code>getGeneratedKeys</code>
899      * @return <code>true</code> if the first result is a <code>ResultSet</code>
900      *         object; <code>false</code> if it is an update count or there
901      *         are no results
902      * @exception SQLException if a database access error occurs
903      *
904      * @since java 1.4
905      */
906     public boolean execute(String sql, int columnIndexes[]) throws SQLException {
907         checkIsOpen();
908         return delegate_.execute(sql, columnIndexes);
909     }
910 
911 
912     /***
913      * Executes the given SQL statement, which may return multiple results,
914      * and signals the driver that the
915      * auto-generated keys indicated in the given array should be made available
916      * for retrieval. This array contains the names of the columns in the
917      * target table that contain the auto-generated keys that should be made
918      * available. The driver will ignore the array if the given SQL statement
919      * is not an <code>INSERT</code> statement.
920      * <P>
921      * In some (uncommon) situations, a single SQL statement may return
922      * multiple result sets and/or update counts.  Normally you can ignore
923      * this unless you are (1) executing a stored procedure that you know may
924      * return multiple results or (2) you are dynamically executing an
925      * unknown SQL string.
926      * <P>
927      * The <code>execute</code> method executes an SQL statement and indicates the
928      * form of the first result.  You must then use the methods
929      * <code>getResultSet</code> or <code>getUpdateCount</code>
930      * to retrieve the result, and <code>getMoreResults</code> to
931      * move to any subsequent result(s).
932      *
933      * @param sql any SQL statement
934      * @param columnNames an array of the names of the columns in the inserted
935      *        row that should be made available for retrieval by a call to the
936      *        method <code>getGeneratedKeys</code>
937      * @return <code>true</code> if the next result is a <code>ResultSet</code>
938      *         object; <code>false</code> if it is an update count or there
939      *         are no more results
940      * @exception SQLException if a database access error occurs
941      *
942      * @since java 1.4
943      */
944     public boolean execute(String sql, String columnNames[]) throws SQLException {
945         checkIsOpen();
946         return delegate_.execute(sql, columnNames);
947     }
948 
949 
950    /***
951      * Retrieves the result set holdability for <code>ResultSet</code> objects
952      * generated by this <code>Statement</code> object.
953      *
954      * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
955      *         <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
956      * @exception SQLException if a database access error occurs
957      *
958      * @since java 1.4
959      */
960     public int getResultSetHoldability() throws SQLException {
961         checkIsOpen();
962         return delegate_.getResultSetHoldability();
963     }
964 }
965