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 com.gargoylesoftware.base.resource.ManagedResource;
41  import java.sql.CallableStatement;
42  import java.sql.Connection;
43  import java.sql.DatabaseMetaData;
44  import java.sql.PreparedStatement;
45  import java.sql.Savepoint;
46  import java.sql.SQLException;
47  import java.sql.SQLWarning;
48  import java.sql.Statement;
49  import java.util.ArrayList;
50  import java.util.Collections;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  
55  /***
56   *  A wrapper for java.sql.Connection objects.<p>
57   *
58   *  The contract with JDBC says that result sets must be closed before
59   *  statements and statements must be closed before connections but java does
60   *  not enforce this contract. It is quite possible to close a connection while
61   *  statements and result sets are still open. While some database drivers
62   *  handle this condition nicely, others will start failing in undefined ways
63   *  when this happens.<p>
64   *
65   *  This wrapper class is a solution to this problem. If the connection is only
66   *  accessed through the wrapper then the wrapper will ensure that everything is
67   *  closed in the correct order. It will also ensure that the various jdbc
68   *  objects (connections, statements, result sets and metadata) cannot be used
69   *  after they are closed.<p>
70   *
71   *  This class was created for the {@link JDBCResourceFactory} but can be used
72   *  by itself.
73   *
74   * @version  $Revision: 1.5 $
75   * @author  <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
76   */
77  public final class ConnectionWrapper implements Connection, ManagedResource {
78  
79      private Connection delegate_ = null;
80      private boolean isOpen_ = true;
81      private String resourceFactoryName_;
82  
83      private final List openStatements_ = Collections.synchronizedList(new ArrayList());
84      private final List openDatabaseMetaData_ = Collections.synchronizedList(new ArrayList());
85  
86  
87      /***
88       *  Create a new connection wrapper
89       *
90       * @param  connection The connection that we are wrapping
91       */
92      public ConnectionWrapper( final Connection connection ) {
93          if( connection == null ) {
94              throw new NullPointerException();
95          }
96          delegate_ = connection;
97      }
98  
99  
100     /***
101      *  Set the name of the factory that allocated this connection
102      *
103      * @param  name The name of the factory
104      */
105     public final void setResourceFactoryName( final String name ) {
106         resourceFactoryName_ = name;
107     }
108 
109 
110     /***
111      *  Sets this connection's auto-commit mode. If a connection is in
112      *  auto-commit mode, then all its SQL statements will be executed and
113      *  committed as individual transactions. Otherwise, its SQL statements are
114      *  grouped into transactions that are terminated by a call to either the
115      *  method <code>commit</code> or the method <code>rollback</code>. By
116      *  default, new connections are in auto-commit mode. <p>
117      *
118      *  The commit occurs when the statement completes or the next execute
119      *  occurs, whichever comes first. In the case of statements returning a
120      *  ResultSet, the statement completes when the last row of the ResultSet
121      *  has been retrieved or the ResultSet has been closed. In advanced cases,
122      *  a single statement may return multiple results as well as output
123      *  parameter values. In these cases the commit occurs when all results and
124      *  output parameter values have been retrieved.
125      *
126      * @param  autoCommit true enables auto-commit; false disables auto-commit.
127      * @exception  SQLException if a database access error occurs
128      */
129     public void setAutoCommit( boolean autoCommit )
130         throws SQLException {
131         checkConnection();
132         delegate_.setAutoCommit( autoCommit );
133     }
134 
135 
136     /***
137      *  Puts this connection in read-only mode as a hint to enable database
138      *  optimizations. <P>
139      *
140      *  <B>Note:</B> This method cannot be called while in the middle of a
141      *  transaction.
142      *
143      * @param  readOnly true enables read-only mode; false disables read-only
144      *      mode.
145      * @exception  SQLException if a database access error occurs
146      */
147     public void setReadOnly( boolean readOnly )
148         throws SQLException {
149         checkConnection();
150         delegate_.setReadOnly( readOnly );
151     }
152 
153 
154     /***
155      *  Sets a catalog name in order to select a subspace of this Connection's
156      *  database in which to work. If the driver does not support catalogs, it
157      *  will silently ignore this request.
158      *
159      * @param  catalog The catalog name
160      * @exception  SQLException if a database access error occurs
161      */
162     public void setCatalog( String catalog )
163         throws SQLException {
164         checkConnection();
165         delegate_.setCatalog( catalog );
166     }
167 
168 
169     /***
170      *  Attempts to change the transaction isolation level to the one given. The
171      *  constants defined in the interface <code>Connection</code> are the
172      *  possible transaction isolation levels. <P>
173      *
174      *  <B>Note:</B> This method cannot be called while in the middle of a
175      *  transaction.
176      *
177      * @param  level one of the TRANSACTION_* isolation values with the
178      *      exception of TRANSACTION_NONE; some databases may not support other
179      *      values
180      * @exception  SQLException if a database access error occurs
181      */
182     public void setTransactionIsolation( int level )
183         throws SQLException {
184         checkConnection();
185         delegate_.setTransactionIsolation( level );
186     }
187 
188 
189     /***
190      *  Installs the given type map as the type map for this connection. The
191      *  type map will be used for the custom mapping of SQL structured types and
192      *  distinct types.
193      *
194      * @param  map the <code>java.util.Map</code> object to install as the
195      *      replacement for this <code>Connection</code> object's default type
196      *      map
197      * @exception  SQLException If a sql error occurs
198      * @since  1.2
199      */
200     public void setTypeMap( final Map map )
201         throws SQLException {
202         checkConnection();
203         delegate_.setTypeMap( map );
204     }
205 
206 
207     /***
208      *  Return the name of the factory that allocated this connection
209      *
210      * @return  The name of the factory
211      */
212     public final String getResourceFactoryName() {
213         return resourceFactoryName_;
214     }
215 
216 
217     /***
218      *  Return the wrapped connection
219      *
220      * @return  The wrapped connection
221      */
222     public final Connection getDelegate() {
223         return delegate_;
224     }
225 
226 
227     /***
228      *  Gets the current auto-commit state.
229      *
230      * @return  the current state of auto-commit mode
231      * @exception  SQLException if a database access error occurs
232      * @see  #setAutoCommit
233      */
234     public boolean getAutoCommit()
235         throws SQLException {
236         checkConnection();
237         return delegate_.getAutoCommit();
238     }
239 
240 
241     /***
242      *  Tests to see if a Connection is closed.
243      *
244      * @return  true if the connection is closed; false if it's still open
245      * @exception  SQLException if a database access error occurs
246      */
247     public boolean isClosed()
248         throws SQLException {
249 
250         if( delegate_ == null ) {
251             return true;
252         }
253 
254         return delegate_.isClosed();
255     }
256 
257     //======================================================================
258     // Advanced features:
259 
260     /***
261      *  Gets the metadata regarding this connection's database. A Connection's
262      *  database is able to provide information describing its tables, its
263      *  supported SQL grammar, its stored procedures, the capabilities of this
264      *  connection, and so on. This information is made available through a
265      *  DatabaseMetaData object.
266      *
267      * @return  a DatabaseMetaData object for this Connection
268      * @exception  SQLException if a database access error occurs
269      */
270     public DatabaseMetaData getMetaData()
271         throws SQLException {
272         checkConnection();
273         final DatabaseMetaDataWrapper wrapper
274                  = new DatabaseMetaDataWrapper( delegate_.getMetaData() );
275         wrapper.setConnection( this );
276         openDatabaseMetaData_.add( wrapper );
277         return wrapper;
278     }
279 
280 
281     /***
282      *  Tests to see if the connection is in read-only mode.
283      *
284      * @return  true if connection is read-only and false otherwise
285      * @exception  SQLException if a database access error occurs
286      */
287     public boolean isReadOnly()
288         throws SQLException {
289         checkConnection();
290         return delegate_.isReadOnly();
291     }
292 
293 
294     /***
295      *  Returns the Connection's current catalog name.
296      *
297      * @return  the current catalog name or null
298      * @exception  SQLException if a database access error occurs
299      */
300     public String getCatalog()
301         throws SQLException {
302         checkConnection();
303         return delegate_.getCatalog();
304     }
305 
306 
307     /***
308      *  Gets this Connection's current transaction isolation level.
309      *
310      * @return  the current TRANSACTION_* mode value
311      * @exception  SQLException if a database access error occurs
312      */
313     public int getTransactionIsolation()
314         throws SQLException {
315         checkConnection();
316         return delegate_.getTransactionIsolation();
317     }
318 
319 
320     /***
321      *  Returns the first warning reported by calls on this Connection. <P>
322      *
323      *  <B>Note:</B> Subsequent warnings will be chained to this SQLWarning.
324      *
325      * @return  the first SQLWarning or null
326      * @exception  SQLException if a database access error occurs
327      */
328     public SQLWarning getWarnings()
329         throws SQLException {
330         checkConnection();
331         return delegate_.getWarnings();
332     }
333 
334 
335     /***
336      *  Gets the type map object associated with this connection. Unless the
337      *  application has added an entry to the type map, the map returned will be
338      *  empty.
339      *
340      * @return  the <code>java.util.Map</code> object associated with this
341      *      <code>Connection</code> object
342      * @exception  SQLException If a sql error occurs
343      * @since  1.2
344      */
345     public Map getTypeMap()
346         throws SQLException {
347         checkConnection();
348         return delegate_.getTypeMap();
349     }
350 
351 
352     /***
353      *  Creates a <code>Statement</code> object for sending SQL statements to
354      *  the database. SQL statements without parameters are normally executed
355      *  using Statement objects. If the same SQL statement is executed many
356      *  times, it is more efficient to use a <code>PreparedStatement</code>
357      *  object. <P>
358      *
359      *  Result sets created using the returned <code>Statement</code> object
360      *  will by default have forward-only type and read-only concurrency.
361      *
362      * @return  a new Statement object
363      * @exception  SQLException if a database access error occurs
364      */
365     public Statement createStatement()
366         throws SQLException {
367         checkConnection();
368         final StatementWrapper wrapper = new StatementWrapper( delegate_.createStatement() );
369         wrapper.setConnection( this );
370         openStatements_.add( wrapper );
371         return wrapper;
372     }
373 
374 
375     /***
376      *  Creates a <code>PreparedStatement</code> object for sending
377      *  parameterized SQL statements to the database. A SQL statement with or
378      *  without IN parameters can be pre-compiled and stored in a
379      *  PreparedStatement object. This object can then be used to efficiently
380      *  execute this statement multiple times. <P>
381      *
382      *  <B>Note:</B> This method is optimized for handling parametric SQL
383      *  statements that benefit from precompilation. If the driver supports
384      *  precompilation, the method <code>prepareStatement</code> will send the
385      *  statement to the database for precompilation. Some drivers may not
386      *  support precompilation. In this case, the statement may not be sent to
387      *  the database until the <code>PreparedStatement</code> is executed. This
388      *  has no direct effect on users; however, it does affect which method
389      *  throws certain SQLExceptions. <p>
390      *
391      *  Result sets created using the returned PreparedStatement will have
392      *  forward-only type and read-only concurrency, by default.
393      *
394      * @param  sql a SQL statement that may contain one or more '?' IN parameter
395      *      placeholders
396      * @return  a new PreparedStatement object containing the pre-compiled
397      *      statement
398      * @exception  SQLException if a database access error occurs
399      */
400     public PreparedStatement prepareStatement( String sql )
401         throws SQLException {
402         checkConnection();
403         final PreparedStatement statement = new PreparedStatementWrapper( delegate_.prepareStatement( sql ) );
404         openStatements_.add( statement );
405         return statement;
406     }
407 
408 
409     /***
410      *  Creates a <code>CallableStatement</code> object for calling database
411      *  stored procedures. The <code>CallableStatement</code> object provides
412      *  methods for setting up its IN and OUT parameters, and methods for
413      *  executing the call to a stored procedure. <P>
414      *
415      *  <B>Note:</B> This method is optimized for handling stored procedure call
416      *  statements. Some drivers may send the call statement to the database
417      *  when the method <code>prepareCall</code> is done; others may wait until
418      *  the <code>CallableStatement</code> object is executed. This has no
419      *  direct effect on users; however, it does affect which method throws
420      *  certain SQLExceptions. Result sets created using the returned
421      *  CallableStatement will have forward-only type and read-only concurrency,
422      *  by default.
423      *
424      * @param  sql a SQL statement that may contain one or more '?' parameter
425      *      placeholders. Typically this statement is a JDBC function call
426      *      escape string.
427      * @return  a new CallableStatement object containing the pre-compiled SQL
428      *      statement
429      * @exception  SQLException if a database access error occurs
430      */
431     public CallableStatement prepareCall( String sql )
432         throws SQLException {
433         checkConnection();
434         final CallableStatement statement
435                  = new CallableStatementWrapper( delegate_.prepareCall( sql ) );
436         openStatements_.add( statement );
437         return statement;
438     }
439 
440 
441     /***
442      *  Converts the given SQL statement into the system's native SQL grammar. A
443      *  driver may convert the JDBC sql grammar into its system's native SQL
444      *  grammar prior to sending it; this method returns the native form of the
445      *  statement that the driver would have sent.
446      *
447      * @param  sql a SQL statement that may contain one or more '?' parameter
448      *      placeholders
449      * @return  the native form of this statement
450      * @exception  SQLException if a database access error occurs
451      */
452     public String nativeSQL( String sql )
453         throws SQLException {
454         checkConnection();
455         return delegate_.nativeSQL( sql );
456     }
457 
458 
459     /***
460      *  Makes all changes made since the previous commit/rollback permanent and
461      *  releases any database locks currently held by the Connection. This
462      *  method should be used only when auto-commit mode has been disabled.
463      *
464      * @exception  SQLException if a database access error occurs
465      * @see  #setAutoCommit
466      */
467     public void commit()
468         throws SQLException {
469         checkConnection();
470         delegate_.commit();
471     }
472 
473 
474     /***
475      *  Drops all changes made since the previous commit/rollback and releases
476      *  any database locks currently held by this Connection. This method should
477      *  be used only when auto- commit has been disabled.
478      *
479      * @exception  SQLException if a database access error occurs
480      * @see  #setAutoCommit
481      */
482     public void rollback()
483         throws SQLException {
484         checkConnection();
485         delegate_.rollback();
486     }
487 
488 
489     /***
490      *  Releases a Connection's database and JDBC resources immediately instead
491      *  of waiting for them to be automatically released. <P>
492      *
493      *  <B>Note:</B> A Connection is automatically closed when it is garbage
494      *  collected. Certain fatal errors also result in a closed Connection.
495      *
496      * @exception  SQLException if a database access error occurs
497      */
498     public void close()
499         throws SQLException {
500         if( isOpen_ ) {
501             closeAnyOpenStatements();
502             closeAnyOpenMetaDatas();
503 
504             delegate_.close();
505             delegate_ = null;
506         }
507         else {
508             throw new AlreadyClosedException( "Connection is closed" );
509         }
510         isOpen_ = false;
511     }
512 
513 
514     /***
515      *  Close any open statements
516      *
517      * @exception  SQLException If an error occurs
518      */
519     public void closeAnyOpenStatements()
520         throws SQLException {
521         StatementWrapper statement;
522         Iterator iterator = openStatements_.iterator();
523         while( iterator.hasNext() ) {
524             statement = ( StatementWrapper )iterator.next();
525             if( statement.isClosed() == false ) {
526                 statement.close();
527             }
528         }
529         openStatements_.clear();
530     }
531 
532 
533     /***
534      *  Close any open DatabaseMetaData objects
535      *
536      * @exception  SQLException If an error occurs
537      */
538     public void closeAnyOpenMetaDatas()
539         throws SQLException {
540         final Iterator iterator = openDatabaseMetaData_.iterator();
541         while( iterator.hasNext() ) {
542             ( ( DatabaseMetaDataWrapper )iterator.next() ).close();
543         }
544         openDatabaseMetaData_.clear();
545     }
546 
547 
548     /***
549      *  Clears all warnings reported for this <code>Connection</code> object.
550      *  After a call to this method, the method <code>getWarnings</code> returns
551      *  null until a new warning is reported for this Connection.
552      *
553      * @exception  SQLException if a database access error occurs
554      */
555     public void clearWarnings()
556         throws SQLException {
557         checkConnection();
558         delegate_.clearWarnings();
559     }
560 
561 
562     //--------------------------JDBC 2.0-----------------------------
563 
564     /***
565      *  Creates a <code>Statement</code> object that will generate <code>ResultSet</code>
566      *  objects with the given type and concurrency. This method is the same as
567      *  the <code>createStatement</code> method above, but it allows the default
568      *  result set type and result set concurrency type to be overridden.
569      *
570      * @param  resultSetType a result set type; see ResultSet.TYPE_XXX
571      * @param  resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
572      * @return  a new Statement object
573      * @exception  SQLException if a database access error occurs
574      * @since  1.2
575      */
576     public Statement createStatement( int resultSetType, int resultSetConcurrency )
577         throws
578             SQLException {
579 
580         checkConnection();
581         final StatementWrapper wrapper
582             = new StatementWrapper( delegate_.createStatement( resultSetType, resultSetConcurrency ) );
583         openStatements_.add( wrapper );
584         return wrapper;
585     }
586 
587 
588     /***
589      *  Creates a <code>PreparedStatement</code> object that will generate
590      *  <code>ResultSet</code> objects with the given type and concurrency. This
591      *  method is the same as the <code>prepareStatement</code> method above,
592      *  but it allows the default result set type and result set concurrency
593      *  type to be overridden.
594      *
595      * @param  sql a SQL statement that may contain one or more '?' parameter
596      *      placeholders. Typically this statement is a JDBC function call
597      *      escape string.
598      * @param  resultSetType a result set type; see ResultSet.TYPE_XXX
599      * @param  resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
600      * @return  a new PreparedStatement object containing the pre-compiled SQL
601      *      statement
602      * @exception  SQLException if a database access error occurs
603      * @since  1.2
604      */
605     public PreparedStatement prepareStatement(
606             final String sql,
607             final int resultSetType,
608             final int resultSetConcurrency )
609         throws
610             SQLException {
611 
612         checkConnection();
613         final PreparedStatement statement
614             = new PreparedStatementWrapper(
615                 delegate_.prepareStatement( sql, resultSetType, resultSetConcurrency ) );
616         openStatements_.add( statement );
617         return statement;
618     }
619 
620 
621     /***
622      *  Creates a <code>CallableStatement</code> object that will generate
623      *  <code>ResultSet</code> objects with the given type and concurrency. This
624      *  method is the same as the <code>prepareCall</code> method above, but it
625      *  allows the default result set type and result set concurrency type to be
626      *  overridden.
627      *
628      * @param  sql a SQL statement that may contain one or more '?' parameter
629      *      placeholders. Typically this statement is a JDBC function call
630      *      escape string.
631      * @param  resultSetType a result set type; see ResultSet.TYPE_XXX
632      * @param  resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
633      * @return  a new CallableStatement object containing the pre-compiled SQL
634      *      statement
635      * @exception  SQLException if a database access error occurs
636      * @since  1.2
637      */
638     public CallableStatement prepareCall( String sql, int resultSetType,
639             int resultSetConcurrency )
640         throws SQLException {
641         checkConnection();
642         final CallableStatement statement
643                  = new CallableStatementWrapper( delegate_.prepareCall( sql, resultSetType, resultSetConcurrency ) );
644         openStatements_.add( statement );
645         return statement;
646     }
647 
648 
649     /***
650      *  Check to see if the connection is still open. If not, throw an
651      *  exception.
652      *
653      * @exception  SQLException
654      */
655     private void checkConnection()
656         throws SQLException {
657         if( isOpen_ == false ) {
658             throw new SQLException( "Methods cannot be invoked on a closed connection" );
659         }
660     }
661 
662 
663     /***
664      * Return the number of statements that are currently open.  Useful for debugging purposes.
665      *
666      * @return The number of statements that are currently open.
667      */
668     public int getOpenStatementCount() {
669         synchronized(openStatements_) {
670             int count = 0;
671             final Iterator iterator = openStatements_.iterator();
672             while( iterator.hasNext() ) {
673                 final StatementWrapper statement = (StatementWrapper)iterator.next();
674                 if( statement.isClosed() ) {
675                     iterator.remove();
676                 }
677                 else {
678                     count++;
679                 }
680             }
681 
682             return count;
683         }
684     }
685 
686 
687     /***
688      * Changes the holdability of <code>ResultSet</code> objects
689      * created using this <code>Connection</code> object to the given
690      * holdability.
691      *
692      * @param holdability a <code>ResultSet</code> holdability constant; one of
693      *        <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
694      *        <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
695      * @throws SQLException if a database access occurs, the given parameter
696      *         is not a <code>ResultSet</code> constant indicating holdability,
697      *         or the given holdability is not supported
698      * @see #getHoldability
699      * @see java.sql.ResultSet
700      * @since 1.4
701      */
702     public void setHoldability(int holdability) throws SQLException {
703         checkConnection();
704         delegate_.setHoldability(holdability);
705     }
706 
707 
708     /***
709      * Retrieves the current holdability of <code>ResultSet</code> objects
710      * created using this <code>Connection</code> object.
711      *
712      * @return the holdability, one of
713      *        <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
714      *        <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
715      * @throws SQLException if a database access occurs
716      * @see #setHoldability
717      * @see java.sql.ResultSet
718      * @since 1.4
719      */
720     public int getHoldability() throws SQLException {
721         checkConnection();
722         return delegate_.getHoldability();
723     }
724 
725 
726     /***
727      * Creates an unnamed savepoint in the current transaction and
728      * returns the new <code>Savepoint</code> object that represents it.
729      *
730      * @return the new <code>Savepoint</code> object
731      * @exception SQLException if a database access error occurs
732      *            or this <code>Connection</code> object is currently in
733      *            auto-commit mode
734      * @see Savepoint
735      * @since 1.4
736      */
737     public Savepoint setSavepoint() throws SQLException {
738         checkConnection();
739         return delegate_.setSavepoint();
740     }
741 
742 
743     /***
744      * Creates a savepoint with the given name in the current transaction
745      * and returns the new <code>Savepoint</code> object that represents it.
746      *
747      * @param name a <code>String</code> containing the name of the savepoint
748      * @return the new <code>Savepoint</code> object
749      * @exception SQLException if a database access error occurs
750      *            or this <code>Connection</code> object is currently in
751      *            auto-commit mode
752      * @see Savepoint
753      * @since 1.4
754      */
755     public Savepoint setSavepoint(String name) throws SQLException {
756         checkConnection();
757         return delegate_.setSavepoint(name);
758     }
759 
760 
761     /***
762      * Undoes all changes made after the given <code>Savepoint</code> object
763      * was set.
764      * <P>
765      * This method should be used only when auto-commit has been disabled.
766      *
767      * @param savepoint the <code>Savepoint</code> object to roll back to
768      * @exception SQLException if a database access error occurs,
769      *            the <code>Savepoint</code> object is no longer valid,
770      *            or this <code>Connection</code> object is currently in
771      *            auto-commit mode
772      * @see Savepoint
773      * @since 1.4
774      */
775     public void rollback(Savepoint savepoint) throws SQLException {
776         checkConnection();
777         delegate_.rollback(savepoint);
778     }
779 
780 
781     /***
782      * Removes the given <code>Savepoint</code> object from the current
783      * transaction. Any reference to the savepoint after it have been removed
784      * will cause an <code>SQLException</code> to be thrown.
785      *
786      * @param savepoint the <code>Savepoint</code> object to be removed
787      * @exception SQLException if a database access error occurs or
788      *            the given <code>Savepoint</code> object is not a valid
789      *            savepoint in the current transaction
790      * @since 1.4
791      */
792     public void releaseSavepoint(Savepoint savepoint) throws SQLException {
793         checkConnection();
794         delegate_.releaseSavepoint(savepoint);
795     }
796 
797 
798     /***
799      * Creates a <code>Statement</code> object that will generate
800      * <code>ResultSet</code> objects with the given type, concurrency,
801      * and holdability.
802      * This method is the same as the <code>createStatement</code> method
803      * above, but it allows the default result set
804      * type, concurrency, and holdability to be overridden.
805      *
806      * @param resultSetType one of the following <code>ResultSet</code>
807      *        constants:
808      *         <code>ResultSet.TYPE_FORWARD_ONLY</code>,
809      *         <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
810      *         <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
811      * @param resultSetConcurrency one of the following <code>ResultSet</code>
812      *        constants:
813      *         <code>ResultSet.CONCUR_READ_ONLY</code> or
814      *         <code>ResultSet.CONCUR_UPDATABLE</code>
815      * @param resultSetHoldability one of the following <code>ResultSet</code>
816      *        constants:
817      *         <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
818      *         <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
819      * @return a new <code>Statement</code> object that will generate
820      *         <code>ResultSet</code> objects with the given type,
821      *         concurrency, and holdability
822      * @exception SQLException if a database access error occurs
823      *            or the given parameters are not <code>ResultSet</code>
824      *            constants indicating type, concurrency, and holdability
825      * @see java.sql.ResultSet
826      * @since 1.4
827      */
828     public Statement createStatement(int resultSetType, int resultSetConcurrency,
829         int resultSetHoldability) throws SQLException {
830         checkConnection();
831 
832         final Statement statement = new StatementWrapper(
833             delegate_.createStatement( resultSetType, resultSetConcurrency, resultSetHoldability ) );
834         openStatements_.add( statement );
835         return statement;
836     }
837 
838 
839     /***
840      * Creates a <code>PreparedStatement</code> object that will generate
841      * <code>ResultSet</code> objects with the given type, concurrency,
842      * and holdability.
843      * <P>
844      * This method is the same as the <code>prepareStatement</code> method
845      * above, but it allows the default result set
846      * type, concurrency, and holdability to be overridden.
847      *
848      * @param sql a <code>String</code> object that is the SQL statement to
849      *            be sent to the database; may contain one or more ? IN
850      *            parameters
851      * @param resultSetType one of the following <code>ResultSet</code>
852      *        constants:
853      *         <code>ResultSet.TYPE_FORWARD_ONLY</code>,
854      *         <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
855      *         <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
856      * @param resultSetConcurrency one of the following <code>ResultSet</code>
857      *        constants:
858      *         <code>ResultSet.CONCUR_READ_ONLY</code> or
859      *         <code>ResultSet.CONCUR_UPDATABLE</code>
860      * @param resultSetHoldability one of the following <code>ResultSet</code>
861      *        constants:
862      *         <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
863      *         <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
864      * @return a new <code>PreparedStatement</code> object, containing the
865      *         pre-compiled SQL statement, that will generate
866      *         <code>ResultSet</code> objects with the given type,
867      *         concurrency, and holdability
868      * @exception SQLException if a database access error occurs
869      *            or the given parameters are not <code>ResultSet</code>
870      *            constants indicating type, concurrency, and holdability
871      * @see java.sql.ResultSet
872      * @since 1.4
873      */
874     public PreparedStatement prepareStatement(String sql, int resultSetType,
875         int resultSetConcurrency, int resultSetHoldability) throws SQLException {
876         checkConnection();
877 
878         final PreparedStatement statement = new PreparedStatementWrapper(
879             delegate_.prepareStatement( sql, resultSetType, resultSetConcurrency, resultSetHoldability ) );
880         openStatements_.add( statement );
881         return statement;
882     }
883 
884 
885     /***
886      * Creates a <code>CallableStatement</code> object that will generate
887      * <code>ResultSet</code> objects with the given type and concurrency.
888      * This method is the same as the <code>prepareCall</code> method
889      * above, but it allows the default result set
890      * type, result set concurrency type and holdability to be overridden.
891      *
892      * @param sql a <code>String</code> object that is the SQL statement to
893      *            be sent to the database; may contain on or more ? parameters
894      * @param resultSetType one of the following <code>ResultSet</code>
895      *        constants:
896      *         <code>ResultSet.TYPE_FORWARD_ONLY</code>,
897      *         <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
898      *         <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
899      * @param resultSetConcurrency one of the following <code>ResultSet</code>
900      *        constants:
901      *         <code>ResultSet.CONCUR_READ_ONLY</code> or
902      *         <code>ResultSet.CONCUR_UPDATABLE</code>
903      * @param resultSetHoldability one of the following <code>ResultSet</code>
904      *        constants:
905      *         <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
906      *         <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
907      * @return a new <code>CallableStatement</code> object, containing the
908      *         pre-compiled SQL statement, that will generate
909      *         <code>ResultSet</code> objects with the given type,
910      *         concurrency, and holdability
911      * @exception SQLException if a database access error occurs
912      *            or the given parameters are not <code>ResultSet</code>
913      *            constants indicating type, concurrency, and holdability
914      * @see java.sql.ResultSet
915      * @since 1.4
916      */
917     public CallableStatement prepareCall(String sql, int resultSetType,
918         int resultSetConcurrency, int resultSetHoldability) throws SQLException {
919         checkConnection();
920 
921         final CallableStatement statement = new CallableStatementWrapper(
922             delegate_.prepareCall( sql, resultSetType, resultSetConcurrency, resultSetHoldability) );
923         openStatements_.add( statement );
924         return statement;
925     }
926 
927 
928     /***
929      * Creates a default <code>PreparedStatement</code> object that has
930      * the capability to retrieve auto-generated keys. The given constant
931      * tells the driver whether it should make auto-generated keys
932      * available for retrieval.  This parameter is ignored if the SQL
933      * statement is not an <code>INSERT</code> statement.
934      * <P>
935      * <B>Note:</B> This method is optimized for handling
936      * parametric SQL statements that benefit from precompilation. If
937      * the driver supports precompilation,
938      * the method <code>prepareStatement</code> will send
939      * the statement to the database for precompilation. Some drivers
940      * may not support precompilation. In this case, the statement may
941      * not be sent to the database until the <code>PreparedStatement</code>
942      * object is executed.  This has no direct effect on users; however, it does
943      * affect which methods throw certain SQLExceptions.
944      * <P>
945      * Result sets created using the returned <code>PreparedStatement</code>
946      * object will by default be type <code>TYPE_FORWARD_ONLY</code>
947      * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
948      *
949      * @param sql an SQL statement that may contain one or more '?' IN
950      *        parameter placeholders
951      * @param autoGeneratedKeys a flag indicating whether auto-generated keys
952      *        should be returned; one of
953      *        <code>Statement.RETURN_GENERATED_KEYS</code> or
954      *        <code>Statement.NO_GENERATED_KEYS</code>
955      * @return a new <code>PreparedStatement</code> object, containing the
956      *         pre-compiled SQL statement, that will have the capability of
957      *         returning auto-generated keys
958      * @exception SQLException if a database access error occurs
959      *         or the given parameter is not a <code>Statement</code>
960      *         constant indicating whether auto-generated keys should be
961      *         returned
962      * @since 1.4
963      */
964     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
965         checkConnection();
966 
967        final PreparedStatement statement
968             = new PreparedStatementWrapper( delegate_.prepareStatement( sql, autoGeneratedKeys ) );
969         openStatements_.add( statement );
970         return statement;
971     }
972 
973 
974     /***
975      * Creates a default <code>PreparedStatement</code> object capable
976      * of returning the auto-generated keys designated by the given array.
977      * This array contains the indexes of the columns in the target
978      * table that contain the auto-generated keys that should be made
979      * available. This array is ignored if the SQL
980      * statement is not an <code>INSERT</code> statement.
981      * <P>
982      * An SQL statement with or without IN parameters can be
983      * pre-compiled and stored in a <code>PreparedStatement</code> object. This
984      * object can then be used to efficiently execute this statement
985      * multiple times.
986      * <P>
987      * <B>Note:</B> This method is optimized for handling
988      * parametric SQL statements that benefit from precompilation. If
989      * the driver supports precompilation,
990      * the method <code>prepareStatement</code> will send
991      * the statement to the database for precompilation. Some drivers
992      * may not support precompilation. In this case, the statement may
993      * not be sent to the database until the <code>PreparedStatement</code>
994      * object is executed.  This has no direct effect on users; however, it does
995      * affect which methods throw certain SQLExceptions.
996      * <P>
997      * Result sets created using the returned <code>PreparedStatement</code>
998      * object will by default be type <code>TYPE_FORWARD_ONLY</code>
999      * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
1000      *
1001      * @param sql an SQL statement that may contain one or more '?' IN
1002      *        parameter placeholders
1003      * @param columnIndexes an array of column indexes indicating the columns
1004      *        that should be returned from the inserted row or rows
1005      * @return a new <code>PreparedStatement</code> object, containing the
1006      *         pre-compiled statement, that is capable of returning the
1007      *         auto-generated keys designated by the given array of column
1008      *         indexes
1009      * @exception SQLException if a database access error occurs
1010      *
1011      * @since 1.4
1012      */
1013     public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
1014         checkConnection();
1015 
1016        final PreparedStatement statement
1017             = new PreparedStatementWrapper( delegate_.prepareStatement( sql, columnIndexes ) );
1018         openStatements_.add( statement );
1019         return statement;
1020     }
1021 
1022 
1023     /***
1024      * Creates a default <code>PreparedStatement</code> object capable
1025      * of returning the auto-generated keys designated by the given array.
1026      * This array contains the names of the columns in the target
1027      * table that contain the auto-generated keys that should be returned.
1028      * This array is ignored if the SQL
1029      * statement is not an <code>INSERT</code> statement.
1030      * <P>
1031      * An SQL statement with or without IN parameters can be
1032      * pre-compiled and stored in a <code>PreparedStatement</code> object. This
1033      * object can then be used to efficiently execute this statement
1034      * multiple times.
1035      * <P>
1036      * <B>Note:</B> This method is optimized for handling
1037      * parametric SQL statements that benefit from precompilation. If
1038      * the driver supports precompilation,
1039      * the method <code>prepareStatement</code> will send
1040      * the statement to the database for precompilation. Some drivers
1041      * may not support precompilation. In this case, the statement may
1042      * not be sent to the database until the <code>PreparedStatement</code>
1043      * object is executed.  This has no direct effect on users; however, it does
1044      * affect which methods throw certain SQLExceptions.
1045      * <P>
1046      * Result sets created using the returned <code>PreparedStatement</code>
1047      * object will by default be type <code>TYPE_FORWARD_ONLY</code>
1048      * and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
1049      *
1050      * @param sql an SQL statement that may contain one or more '?' IN
1051      *        parameter placeholders
1052      * @param columnNames an array of column names indicating the columns
1053      *        that should be returned from the inserted row or rows
1054      * @return a new <code>PreparedStatement</code> object, containing the
1055      *         pre-compiled statement, that is capable of returning the
1056      *         auto-generated keys designated by the given array of column
1057      *         names
1058      * @exception SQLException if a database access error occurs
1059      *
1060      * @since 1.4
1061      */
1062     public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
1063         checkConnection();
1064 
1065        final PreparedStatement statement
1066             = new PreparedStatementWrapper( delegate_.prepareStatement( sql, columnNames ) );
1067         openStatements_.add( statement );
1068         return statement;
1069     }
1070 }
1071