KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > jdbc > EmbedConnection


1 /*
2
3    Derby - Class org.apache.derby.impl.jdbc.EmbedConnection
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.jdbc;
23
24 import org.apache.derby.jdbc.InternalDriver;
25
26 import org.apache.derby.iapi.reference.Attribute;
27 import org.apache.derby.iapi.reference.JDBC20Translation;
28 import org.apache.derby.iapi.reference.JDBC30Translation;
29 import org.apache.derby.iapi.reference.MessageId;
30 import org.apache.derby.iapi.reference.Property;
31 import org.apache.derby.iapi.reference.SQLState;
32
33 import org.apache.derby.iapi.services.context.ContextManager;
34 import org.apache.derby.iapi.services.memory.LowMemory;
35 import org.apache.derby.iapi.services.monitor.Monitor;
36 import org.apache.derby.iapi.services.sanity.SanityManager;
37
38 import org.apache.derby.iapi.jdbc.AuthenticationService;
39 import org.apache.derby.iapi.jdbc.EngineConnection;
40
41 import org.apache.derby.iapi.db.Database;
42 import org.apache.derby.iapi.error.StandardException;
43 import org.apache.derby.iapi.services.i18n.MessageService;
44 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
45 import org.apache.derby.iapi.sql.execute.ExecutionContext;
46 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
47 import org.apache.derby.iapi.store.access.XATransactionController;
48
49 /* can't import due to name overlap:
50 import java.sql.Connection;
51 import java.sql.ResultSet;
52 */

53 import java.sql.PreparedStatement JavaDoc;
54 import java.sql.CallableStatement JavaDoc;
55 import java.sql.DatabaseMetaData JavaDoc;
56 import java.sql.SQLException JavaDoc;
57 import java.sql.SQLWarning JavaDoc;
58 import java.sql.Statement JavaDoc;
59
60 import java.util.Properties JavaDoc;
61
62 import org.apache.derby.impl.jdbc.authentication.NoneAuthenticationServiceImpl;
63
64 /**
65  * Local implementation of Connection for a JDBC driver in
66  * the same process as the database.
67  * <p>
68  * There is always a single root (parent) connection. The
69  * initial JDBC connection is the root connection. A
70  * call to <I>getCurrentConnection()</I> or with the URL
71  * <I>jdbc:default:connection</I> yields a nested connection that shares
72  * the same root connection as the parent. A nested connection
73  * is implemented using this class. The nested connection copies the
74  * state of the parent connection and shares some of the same
75  * objects (e.g. ContextManager) that are shared across all
76  * nesting levels. The proxy also maintains its own
77  * state that is distinct from its parent connection (e.g.
78  * autocommit or warnings).
79  * <p>
80  * <B>SYNCHRONIZATION</B>: Just about all JDBC actions are
81  * synchronized across all connections stemming from the
82  * same root connection. The synchronization is upon
83  * the a synchronized object return by the rootConnection.
84    <P><B>Supports</B>
85    <UL>
86   <LI> JDBC 2.0
87    </UL>
88  *
89  * @author djd
90  *
91  * @see TransactionResourceImpl
92  *
93  */

94 public class EmbedConnection implements EngineConnection
95 {
96
97     private static final StandardException exceptionClose = StandardException.closeException();
98     
99     /**
100      * Static exception to be thrown when a Connection request can not
101      * be fulfilled due to lack of memory. A static exception as the lack
102      * of memory would most likely cause another OutOfMemoryException and
103      * if there is not enough memory to create the OOME exception then something
104      * like the VM dying could occur. Simpler just to throw a static.
105      */

106     public static final SQLException JavaDoc NO_MEM =
107         Util.generateCsSQLException(SQLState.LOGIN_FAILED, "java.lang.OutOfMemoryError");
108     
109     /**
110      * Low memory state object for connection requests.
111      */

112     public static final LowMemory memoryState = new LowMemory();
113
114     //////////////////////////////////////////////////////////
115
// OBJECTS SHARED ACROSS CONNECTION NESTING
116
//////////////////////////////////////////////////////////
117
DatabaseMetaData JavaDoc dbMetadata;
118
119     final TransactionResourceImpl tr; // always access tr thru getTR()
120

121
122     //////////////////////////////////////////////////////////
123
// STATE (copied to new nested connections, but nesting
124
// specific)
125
//////////////////////////////////////////////////////////
126
private boolean active;
127     boolean autoCommit = true;
128     boolean needCommit;
129
130     // Set to true if NONE authentication is being used
131
private boolean usingNoneAuth;
132
133     /*
134      following is a new feature in JDBC3.0 where you can specify the holdability
135      of a resultset at the end of the transaction. This gets set by the
136      new method setHoldability(int) in JDBC3.0
137      *
138      */

139     private int connectionHoldAbility = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
140
141
142     //////////////////////////////////////////////////////////
143
// NESTING SPECIFIC OBJECTS
144
//////////////////////////////////////////////////////////
145
/*
146     ** The root connection is the base connection upon
147     ** which all actions are synchronized. By default,
148     ** we are the root connection unless we are created
149     ** by copying the state from another connection.
150     */

151     final EmbedConnection rootConnection;
152     private SQLWarning JavaDoc topWarning;
153     /**
154         Factory for JDBC objects to be created.
155     */

156     private InternalDriver factory;
157
158     /**
159         The Connection object the application is using when accessing the
160         database through this connection. In most cases this will be equal
161         to this. When Connection pooling is being used, then it will
162         be set to the Connection object handed to the application.
163         It is used for the getConnection() methods of various JDBC objects.
164     */

165     private java.sql.Connection JavaDoc applicationConnection;
166
167     /**
168         An increasing counter to assign to a ResultSet on its creation.
169         Used for ordering ResultSets returned from a procedure, always
170         returned in order of their creation. Is maintained at the root connection.
171     */

172     private int resultSetId;
173     
174     /** Cached string representation of the connection id */
175     private String JavaDoc connString;
176
177
178     //////////////////////////////////////////////////////////
179
// CONSTRUCTORS
180
//////////////////////////////////////////////////////////
181

182     // create a new Local Connection, using a new context manager
183
//
184
public EmbedConnection(InternalDriver driver, String JavaDoc url, Properties JavaDoc info)
185          throws SQLException JavaDoc
186     {
187         // Create a root connection.
188
applicationConnection = rootConnection = this;
189         factory = driver;
190
191
192         tr = new TransactionResourceImpl(driver, url, info);
193
194         active = true;
195
196         // register this thread and its context manager with
197
// the global context service
198
setupContextStack();
199
200         try {
201
202             // stick my context into the context manager
203
EmbedConnectionContext context = pushConnectionContext(tr.getContextManager());
204
205             // if we are shutting down don't attempt to boot or create the database
206
boolean shutdown = Boolean.valueOf(info.getProperty(Attribute.SHUTDOWN_ATTR)).booleanValue();
207
208             // see if database is already booted
209
Database database = (Database) Monitor.findService(Property.DATABASE_MODULE, tr.getDBName());
210
211             // See if user wants to create a new database.
212
boolean createBoot = createBoot(info);
213             if (database != null)
214             {
215                 // database already booted by someone else
216
tr.setDatabase(database);
217             }
218             else if (!shutdown)
219             {
220                 // Return false iff the monitor cannot handle a service of the type
221
// indicated by the proptocol within the name. If that's the case
222
// then we are the wrong driver.
223
if (!bootDatabase(info))
224                 {
225                     tr.clearContextInError();
226                     setInactive();
227                     return;
228                 }
229             }
230
231
232             if (createBoot && !shutdown)
233             {
234                 // if we are shutting down don't attempt to boot or create the database
235

236                 if (tr.getDatabase() != null) {
237                     addWarning(EmbedSQLWarning.newEmbedSQLWarning(SQLState.DATABASE_EXISTS, getDBName()));
238                 } else {
239
240                     // check for user's credential and authenticate the user
241
// with system level authentication service.
242
// FIXME: We should also check for CREATE DATABASE operation
243
// authorization for the user if authorization was
244
// set at the system level.
245
// Right now, the authorization service does not
246
// restrict/account for Create database op.
247
checkUserCredentials(null, info);
248                     
249                     // Process with database creation
250
database = createDatabase(tr.getDBName(), info);
251                     tr.setDatabase(database);
252                 }
253             }
254
255
256             if (tr.getDatabase() == null) {
257                 String JavaDoc dbname = tr.getDBName();
258                 // do not clear the TransactionResource context. It will be restored
259
// as part of the finally clause below.
260
this.setInactive();
261                 throw newSQLException(SQLState.DATABASE_NOT_FOUND, dbname);
262             }
263
264
265             // Check User's credentials and if it is a valid user of
266
// the database
267
//
268
checkUserCredentials(tr.getDBName(), info);
269
270             // Make a real connection into the database, setup lcc, tc and all
271
// the rest.
272
tr.startTransaction();
273
274             // now we have the database connection, we can shut down
275
if (shutdown) {
276                 throw tr.shutdownDatabaseException();
277             }
278
279             // Raise a warning in sqlAuthorization mode if authentication is not ON
280
if (usingNoneAuth && getLanguageConnection().usesSqlAuthorization())
281                 addWarning(EmbedSQLWarning.newEmbedSQLWarning(SQLState.SQL_AUTHORIZATION_WITH_NO_AUTHENTICATION));
282         }
283         catch (OutOfMemoryError JavaDoc noMemory)
284         {
285             //System.out.println("freeA");
286
restoreContextStack();
287             tr.lcc = null;
288             tr.cm = null;
289             
290             //System.out.println("free");
291
//System.out.println(Runtime.getRuntime().freeMemory());
292
memoryState.setLowMemory();
293             
294             //noMemory.printStackTrace();
295
// throw Util.generateCsSQLException(SQLState.LOGIN_FAILED, noMemory.getMessage(), noMemory);
296
throw NO_MEM;
297         }
298         catch (Throwable JavaDoc t) {
299             throw handleException(t);
300         } finally {
301             restoreContextStack();
302         }
303     }
304
305
306     /**
307       Examine the attributes set provided and determine if this is a create
308       boot. A boot is a create boot iff.
309
310       <OL>
311       <LI>create=true - This means create a standard database.
312       <LI> createFrom = Path - creates database from backup if it does not exist.
313       <LI> restoreFrom = Path - database is restored completley from backup.
314            if a database exists in the same place it is replaced by the version
315            in the backup otherwise a new one is created using the backup copy.
316       <LI> rollForwardRecoveryFrom = Path - rollforward is performed
317       using the version backup and any active and archived log files.
318       </OL>
319
320       @param p the attribute set.
321
322       @exception SQLException Ooops.
323       */

324     private boolean createBoot(Properties JavaDoc p) throws SQLException JavaDoc
325     {
326         int createCount = 0;
327
328         if (Boolean.valueOf(p.getProperty(Attribute.CREATE_ATTR)).booleanValue())
329             createCount++;
330
331         int restoreCount=0;
332         //check if the user has specified any /create/restore/recover from backup attributes.
333
if (p.getProperty(Attribute.CREATE_FROM) != null)
334             restoreCount++;
335         if (p.getProperty(Attribute.RESTORE_FROM) != null)
336             restoreCount++;
337         if (p.getProperty(Attribute.ROLL_FORWARD_RECOVERY_FROM)!=null)
338             restoreCount++;
339         if(restoreCount > 1)
340             throw newSQLException(SQLState.CONFLICTING_RESTORE_ATTRIBUTES);
341     
342         // check if user has specified re-encryption attributes
343
// in combination with create/restore/recover attributes.
344
// re-encryption is not allowed when restoring from backup.
345
if (restoreCount != 0 &&
346             (Boolean.valueOf(p.getProperty(
347                             Attribute.DATA_ENCRYPTION)).booleanValue() ||
348              p.getProperty(Attribute.NEW_BOOT_PASSWORD) != null ||
349              p.getProperty(Attribute.NEW_CRYPTO_EXTERNAL_KEY) != null
350              ))
351         {
352             throw newSQLException(SQLState.CONFLICTING_RESTORE_ATTRIBUTES);
353         }
354
355
356         //add the restore count to create count to make sure
357
//user has not specified and restore together by mistake.
358
createCount = createCount + restoreCount ;
359
360         //
361
if (createCount > 1) throw newSQLException(SQLState.CONFLICTING_CREATE_ATTRIBUTES);
362         
363         //retuns true only for the create flag not for restore flags
364
return (createCount - restoreCount) == 1;
365     }
366
367     /**
368      * Create a new connection based off of the
369      * connection passed in. Initializes state
370      * based on input connection, and copies
371      * appropriate object pointers. This is only used
372        for nested connections.
373      *
374      * @param inputConnection the input connection
375      */

376     public EmbedConnection(EmbedConnection inputConnection)
377     {
378         if (SanityManager.DEBUG)
379         {
380             SanityManager.ASSERT(inputConnection.active,
381             "trying to create a proxy for an inactive conneciton");
382         }
383
384         // Proxy connections are always autocommit false
385
// thus needCommit is irrelavent.
386
autoCommit = false;
387
388
389         /*
390         ** Nesting specific state we are copying from
391         ** the inputConnection
392         */

393
394         /*
395         ** Objects we are sharing across nestings
396         */

397         // set it to null to allow it to be final.
398
tr = null; // a proxy connection has no direct
399
// pointer to the tr. Every call has to go
400
// thru the rootConnection's tr.
401
active = true;
402         this.rootConnection = inputConnection.rootConnection;
403         this.applicationConnection = this;
404         this.factory = inputConnection.factory;
405
406         //if no holdability specified for the resultset, use the holability
407
//defined for the connection
408
this.connectionHoldAbility = inputConnection.connectionHoldAbility;
409
410         //RESOLVE: although it looks like the right
411
// thing to share the metadata object, if
412
// we do we'll get the wrong behavior on
413
// getCurrentConnection().getMetaData().isReadOnly()
414
// so don't try to be smart and uncomment the
415
// following. Ultimately, the metadata should
416
// be shared by all connections anyway.
417
//dbMetadata = inputConnection.dbMetadata;
418
}
419
420     //
421
// Check passed-in user's credentials.
422
//
423
private void checkUserCredentials(String JavaDoc dbname,
424                                       Properties JavaDoc userInfo)
425       throws SQLException JavaDoc
426     {
427         if (SanityManager.DEBUG)
428             SanityManager.ASSERT(!isClosed(), "connection is closed");
429
430         // If a database name was passed-in then check user's credential
431
// in that database using the database's authentication service,
432
// otherwise check if it is a valid user in the JBMS system.
433
//
434
// NOTE: We always expect an authentication service per database
435
// and one at the system level.
436
//
437
AuthenticationService authenticationService = null;
438
439         // Retrieve appropriate authentication service handle
440
if (dbname == null)
441             authenticationService = getLocalDriver().getAuthenticationService();
442         else
443             authenticationService = getTR().getDatabase().getAuthenticationService();
444
445         // check that we do have a authentication service
446
// it is _always_ expected.
447
if (authenticationService == null)
448         {
449             String JavaDoc failedString = MessageService.getTextMessage(
450                 (dbname == null) ? MessageId.AUTH_NO_SERVICE_FOR_SYSTEM : MessageId.AUTH_NO_SERVICE_FOR_DB);
451
452             throw newSQLException(SQLState.LOGIN_FAILED, failedString);
453         }
454         
455         // Let's authenticate now
456

457         if (!authenticationService.authenticate(
458                                                dbname,
459                                                userInfo
460                                                )) {
461
462             throw newSQLException(SQLState.LOGIN_FAILED, MessageService.getTextMessage(MessageId.AUTH_INVALID));
463
464         }
465
466         // If authentication is not on, we have to raise a warning if sqlAuthorization is ON
467
// Since NoneAuthenticationService is the default for Derby, it should be ok to refer
468
// to its implementation here, since it will always be present.
469
if (authenticationService instanceof NoneAuthenticationServiceImpl)
470             usingNoneAuth = true;
471     }
472
473     /**
474      * Gets the EngineType of the connected database.
475      *
476      * @return 0 if there is no database, the engine type otherwise. @see org.apache.derby.iapi.reference.EngineType
477      */

478     public int getEngineType()
479     {
480         Database db = getDatabase();
481
482         if( null == db)
483             return 0;
484         return db.getEngineType();
485     }
486     
487     /*
488     ** Methods from java.sql.Connection
489     */

490
491     /**
492      * SQL statements without parameters are normally
493      * executed using Statement objects. If the same SQL statement
494      * is executed many times, it is more efficient to use a
495      * PreparedStatement
496      *
497      * JDBC 2.0
498      *
499      * Result sets created using the returned Statement will have
500      * forward-only type, and read-only concurrency, by default.
501      *
502      * @return a new Statement object
503      * @exception SQLException if a database-access error occurs.
504      */

505     public final Statement JavaDoc createStatement() throws SQLException JavaDoc
506     {
507         return createStatement(JDBC20Translation.TYPE_FORWARD_ONLY,
508                                JDBC20Translation.CONCUR_READ_ONLY,
509                                connectionHoldAbility);
510     }
511
512     /**
513      * JDBC 2.0
514      *
515      * Same as createStatement() above, but allows the default result set
516      * type and result set concurrency type to be overridden.
517      *
518      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
519      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
520      * @return a new Statement object
521       * @exception SQLException if a database-access error occurs.
522     */

523     public final Statement JavaDoc createStatement(int resultSetType,
524                                      int resultSetConcurrency)
525                         throws SQLException JavaDoc
526     {
527         return createStatement(resultSetType, resultSetConcurrency,
528                 connectionHoldAbility);
529     }
530
531     /**
532      * JDBC 3.0
533      *
534      * Same as createStatement() above, but allows the default result set
535      * type, result set concurrency type and result set holdability type to
536      * be overridden.
537      *
538      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
539      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
540      * @param resultSetHoldability a holdability type,
541      * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
542      * @return a new Statement object
543      * @exception SQLException if a database-access error occurs.
544      */

545     public final Statement JavaDoc createStatement(int resultSetType,
546                                      int resultSetConcurrency,
547                                      int resultSetHoldability)
548                         throws SQLException JavaDoc
549     {
550         checkIfClosed();
551
552         return factory.newEmbedStatement(this, false,
553             setResultSetType(resultSetType), resultSetConcurrency,
554             resultSetHoldability);
555     }
556
557     /**
558      * A SQL statement with or without IN parameters can be
559      * pre-compiled and stored in a PreparedStatement object. This
560      * object can then be used to efficiently execute this statement
561      * multiple times.
562      *
563      * <P><B>Note:</B> This method is optimized for handling
564      * parametric SQL statements that benefit from precompilation. If
565      * the driver supports precompilation, prepareStatement will send
566      * the statement to the database for precompilation. Some drivers
567      * may not support precompilation. In this case, the statement may
568      * not be sent to the database until the PreparedStatement is
569      * executed. This has no direct affect on users; however, it does
570      * affect which method throws certain SQLExceptions.
571      *
572      * JDBC 2.0
573      *
574      * Result sets created using the returned PreparedStatement will have
575      * forward-only type, and read-only concurrency, by default.
576      *
577      * @param sql a SQL statement that may contain one or more '?' IN
578      * parameter placeholders
579      * @return a new PreparedStatement object containing the
580      * pre-compiled statement
581      * @exception SQLException if a database-access error occurs.
582      */

583     public final PreparedStatement JavaDoc prepareStatement(String JavaDoc sql)
584         throws SQLException JavaDoc
585     {
586         return prepareStatement(sql,JDBC20Translation.TYPE_FORWARD_ONLY,
587             JDBC20Translation.CONCUR_READ_ONLY,
588             connectionHoldAbility,
589             JDBC30Translation.NO_GENERATED_KEYS,
590             null,
591             null);
592     }
593
594
595     /**
596      * JDBC 2.0
597      *
598      * Same as prepareStatement() above, but allows the default result set
599      * type and result set concurrency type to be overridden.
600      *
601      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
602      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
603      * @return a new PreparedStatement object containing the
604      * pre-compiled SQL statement
605      * @exception SQLException if a database-access error occurs.
606      */

607     public final PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int resultSetType,
608                     int resultSetConcurrency)
609         throws SQLException JavaDoc
610     {
611         return prepareStatement(sql,
612             resultSetType,
613             resultSetConcurrency,
614             connectionHoldAbility,
615             JDBC30Translation.NO_GENERATED_KEYS,
616             null,
617             null);
618     }
619
620     /**
621      * JDBC 3.0
622      *
623      * Same as prepareStatement() above, but allows the default result set
624      * type, result set concurrency type and result set holdability
625      * to be overridden.
626      *
627      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
628      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
629      * @param resultSetHoldability - one of the following ResultSet constants:
630      * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
631      * @return a new PreparedStatement object containing the
632      * pre-compiled SQL statement
633      * @exception SQLException if a database-access error occurs.
634      */

635     public final PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int resultSetType,
636                     int resultSetConcurrency, int resultSetHoldability)
637         throws SQLException JavaDoc
638     {
639         return prepareStatement(sql,
640             resultSetType,
641             resultSetConcurrency,
642             resultSetHoldability,
643             JDBC30Translation.NO_GENERATED_KEYS,
644             null,
645             null);
646     }
647
648
649     /**
650      * Creates a default PreparedStatement object capable of returning
651      * the auto-generated keys designated by the given array. This array contains
652      * the indexes of the columns in the target table that contain the auto-generated
653      * keys that should be made available. This array is ignored if the SQL statement
654      * is not an INSERT statement
655
656         JDBC 3.0
657      *
658      *
659      * @param sql An SQL statement that may contain one or more ? IN parameter placeholders
660      * @param columnIndexes An array of column indexes indicating the columns
661      * that should be returned from the inserted row or rows
662      *
663      * @return A new PreparedStatement object, containing the pre-compiled
664      * SQL statement, that will have the capability of returning auto-generated keys
665      * designated by the given array of column indexes
666      *
667      * @exception SQLException Feature not implemented for now.
668      */

669     public final PreparedStatement JavaDoc prepareStatement(
670             String JavaDoc sql,
671             int[] columnIndexes)
672     throws SQLException JavaDoc
673     {
674         throw Util.notImplemented("prepareStatement(String, int[])");
675     }
676
677     /**
678      * Creates a default PreparedStatement object capable of returning
679      * the auto-generated keys designated by the given array. This array contains
680      * the names of the columns in the target table that contain the auto-generated
681      * keys that should be returned. This array is ignored if the SQL statement
682      * is not an INSERT statement
683      *
684         JDBC 3.0
685      *
686      * @param sql An SQL statement that may contain one or more ? IN parameter placeholders
687      * @param columnNames An array of column names indicating the columns
688      * that should be returned from the inserted row or rows
689      *
690      * @return A new PreparedStatement object, containing the pre-compiled
691      * SQL statement, that will have the capability of returning auto-generated keys
692      * designated by the given array of column names
693      *
694      * @exception SQLException Feature not implemented for now.
695      */

696     public final PreparedStatement JavaDoc prepareStatement(
697             String JavaDoc sql,
698             String JavaDoc[] columnNames)
699     throws SQLException JavaDoc
700     {
701         throw Util.notImplemented("prepareStatement(String, String[])");
702     }
703
704     /**
705      * Creates a default PreparedStatement object that has the capability to
706      * retieve auto-generated keys. The given constant tells the driver
707      * whether it should make auto-generated keys available for retrieval.
708      * This parameter is ignored if the SQL statement is not an INSERT statement.
709      * JDBC 3.0
710      *
711      * @param sql A SQL statement that may contain one or more ? IN parameter placeholders
712      * @param autoGeneratedKeys A flag indicating whether auto-generated keys
713      * should be returned
714      *
715      * @return A new PreparedStatement object, containing the pre-compiled
716      * SQL statement, that will have the capability of returning auto-generated keys
717      *
718      * @exception SQLException Feature not implemented for now.
719      */

720     public final PreparedStatement JavaDoc prepareStatement(
721             String JavaDoc sql,
722             int autoGeneratedKeys)
723     throws SQLException JavaDoc
724     {
725         return prepareStatement(sql,
726             JDBC20Translation.TYPE_FORWARD_ONLY,
727             JDBC20Translation.CONCUR_READ_ONLY,
728             connectionHoldAbility,
729             autoGeneratedKeys,
730             null,
731             null);
732     }
733     
734     private PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int resultSetType,
735                     int resultSetConcurrency, int resultSetHoldability,
736                     int autoGeneratedKeys, int[] columnIndexes, String JavaDoc[] columnNames)
737        throws SQLException JavaDoc
738      {
739         synchronized (getConnectionSynchronization()) {
740                         setupContextStack();
741             try {
742                 return factory.newEmbedPreparedStatement(this, sql, false,
743                                                setResultSetType(resultSetType),
744                                                resultSetConcurrency,
745                                                resultSetHoldability,
746                                                autoGeneratedKeys,
747                                                columnIndexes,
748                                                columnNames);
749             } finally {
750                 restoreContextStack();
751             }
752         }
753      }
754
755     /**
756      * A SQL stored procedure call statement is handled by creating a
757      * CallableStatement for it. The CallableStatement provides
758      * methods for setting up its IN and OUT parameters, and
759      * methods for executing it.
760      *
761      * <P><B>Note:</B> This method is optimized for handling stored
762      * procedure call statements. Some drivers may send the call
763      * statement to the database when the prepareCall is done; others
764      * may wait until the CallableStatement is executed. This has no
765      * direct affect on users; however, it does affect which method
766      * throws certain SQLExceptions.
767      *
768      * JDBC 2.0
769      *
770      * Result sets created using the returned CallableStatement will have
771      * forward-only type, and read-only concurrency, by default.
772      *
773      * @param sql a SQL statement that may contain one or more '?'
774      * parameter placeholders. Typically this statement is a JDBC
775      * function call escape string.
776      * @return a new CallableStatement object containing the
777      * pre-compiled SQL statement
778      * @exception SQLException if a database-access error occurs.
779      */

780     public final CallableStatement JavaDoc prepareCall(String JavaDoc sql)
781         throws SQLException JavaDoc
782     {
783         return prepareCall(sql, JDBC20Translation.TYPE_FORWARD_ONLY,
784                            JDBC20Translation.CONCUR_READ_ONLY,
785                            connectionHoldAbility);
786     }
787
788     /**
789      * JDBC 2.0
790      *
791      * Same as prepareCall() above, but allows the default result set
792      * type and result set concurrency type to be overridden.
793      *
794      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
795      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
796      * @return a new CallableStatement object containing the
797      * pre-compiled SQL statement
798      * @exception SQLException if a database-access error occurs.
799      */

800     public final CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType,
801                  int resultSetConcurrency)
802         throws SQLException JavaDoc
803     {
804         return prepareCall(sql, resultSetType, resultSetConcurrency,
805                            connectionHoldAbility);
806     }
807
808     /**
809      * JDBC 3.0
810      *
811      * Same as prepareCall() above, but allows the default result set
812      * type, result set concurrency type and result set holdability
813      * to be overridden.
814      *
815      * @param resultSetType a result set type, see ResultSet.TYPE_XXX
816      * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX
817      * @param resultSetHoldability - one of the following ResultSet constants:
818      * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
819      * @return a new CallableStatement object containing the
820      * pre-compiled SQL statement
821      * @exception SQLException if a database-access error occurs.
822      */

823     public final CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType,
824                  int resultSetConcurrency, int resultSetHoldability)
825         throws SQLException JavaDoc
826     {
827         checkIfClosed();
828
829         synchronized (getConnectionSynchronization())
830         {
831             setupContextStack();
832             try
833             {
834                 return factory.newEmbedCallableStatement(this, sql,
835                                                setResultSetType(resultSetType),
836                                                resultSetConcurrency,
837                                                resultSetHoldability);
838             }
839             finally
840             {
841                 restoreContextStack();
842             }
843         }
844     }
845
846     /**
847      * A driver may convert the JDBC sql grammar into its system's
848      * native SQL grammar prior to sending it; nativeSQL returns the
849      * native form of the statement that the driver would have sent.
850      *
851      * @param sql a SQL statement that may contain one or more '?'
852      * parameter placeholders
853      * @return the native form of this statement
854      */

855     public String JavaDoc nativeSQL(String JavaDoc sql) throws SQLException JavaDoc {
856         checkIfClosed();
857         // we don't massage the strings at all, so this is easy:
858
return sql;
859     }
860
861     /**
862      * If a connection is in auto-commit mode, then all its SQL
863      * statements will be executed and committed as individual
864      * transactions. Otherwise, its SQL statements are grouped into
865      * transactions that are terminated by either commit() or
866      * rollback(). By default, new connections are in auto-commit
867      * mode.
868      *
869      * The commit occurs when the statement completes or the next
870      * execute occurs, whichever comes first. In the case of
871      * statements returning a ResultSet, the statement completes when
872      * the last row of the ResultSet has been retrieved or the
873      * ResultSet has been closed. In advanced cases, a single
874      * statement may return multiple results as well as output
875      * parameter values. Here the commit occurs when all results and
876      * output param values have been retrieved.
877      *
878      * @param autoCommit true enables auto-commit; false disables
879      * auto-commit.
880      * @exception SQLException if a database-access error occurs.
881      */

882     public void setAutoCommit(boolean autoCommit) throws SQLException JavaDoc {
883         checkIfClosed();
884
885         // Is this a nested connection
886
if (rootConnection != this) {
887             if (autoCommit)
888                 throw newSQLException(SQLState.NO_AUTO_COMMIT_ON);
889         }
890
891         if (this.autoCommit != autoCommit)
892             commit();
893
894         this.autoCommit = autoCommit;
895     }
896
897     /**
898      * Get the current auto-commit state.
899      *
900      * @return Current state of auto-commit mode.
901      * @see #setAutoCommit
902      */

903     public boolean getAutoCommit() throws SQLException JavaDoc {
904         checkIfClosed();
905         return autoCommit;
906     }
907
908     /**
909      * Commit makes all changes made since the previous
910      * commit/rollback permanent and releases any database locks
911      * currently held by the Connection. This method should only be
912      * used when auto commit has been disabled.
913      *
914      * @exception SQLException if a database-access error occurs.
915      * @see #setAutoCommit
916      */

917     public void commit() throws SQLException JavaDoc {
918         synchronized (getConnectionSynchronization())
919         {
920             /*
921             ** Note that the context stack is
922             ** needed even for rollback & commit
923             */

924             setupContextStack();
925
926             try
927             {
928                 getTR().commit();
929             }
930             catch (Throwable JavaDoc t)
931             {
932                 throw handleException(t);
933             }
934             finally
935             {
936                 restoreContextStack();
937             }
938
939             needCommit = false;
940         }
941     }
942
943     /**
944      * Rollback drops all changes made since the previous
945      * commit/rollback and releases any database locks currently held
946      * by the Connection. This method should only be used when auto
947      * commit has been disabled.
948      *
949      * @exception SQLException if a database-access error occurs.
950      * @see #setAutoCommit
951      */

952     public void rollback() throws SQLException JavaDoc {
953
954         synchronized (getConnectionSynchronization())
955         {
956             /*
957             ** Note that the context stack is
958             ** needed even for rollback & commit
959             */

960             setupContextStack();
961             try
962             {
963                 getTR().rollback();
964             } catch (Throwable JavaDoc t) {
965                 throw handleException(t);
966             }
967             finally
968             {
969                 restoreContextStack();
970             }
971             needCommit = false;
972         }
973     }
974
975     /**
976      * In some cases, it is desirable to immediately release a
977      * Connection's database and JDBC resources instead of waiting for
978      * them to be automatically released; the close method provides this
979      * immediate release.
980      *
981      * <P><B>Note:</B> A Connection is automatically closed when it is
982      * garbage collected. Certain fatal errors also result in a closed
983      * Connection.
984      *
985      * @exception SQLException if a database-access error occurs.
986      */

987     public void close() throws SQLException JavaDoc {
988         // JDK 1.4 javadoc indicates close on a closed connection is a no-op
989
if (isClosed())
990             return;
991
992
993         if (rootConnection == this)
994         {
995             /* Throw error to match DB2/JDBC if a tran is pending in non-autocommit mode */
996             if (!autoCommit && !transactionIsIdle()) {
997                 throw newSQLException(SQLState.LANG_INVALID_TRANSACTION_STATE);
998             }
999
1000            close(exceptionClose);
1001        }
1002        else
1003            setInactive(); // nested connection
1004
}
1005
1006    // This inner close takes the exception and calls
1007
// the context manager to make the connection close.
1008
// The exception must be a session severity exception.
1009
//
1010
// NOTE: This method is not part of JDBC specs.
1011
//
1012
private void close(StandardException e) throws SQLException JavaDoc {
1013        
1014        synchronized(getConnectionSynchronization())
1015        {
1016            if (rootConnection == this)
1017            {
1018                /*
1019                 * If it isn't active, it's already been closed.
1020                 */

1021                if (active) {
1022                    setupContextStack();
1023                    try {
1024                        tr.rollback();
1025
1026                        // Let go of lcc reference so it can be GC'ed after
1027
// cleanupOnError, the tr will stay around until the
1028
// rootConnection itself is GC'ed, which is dependent
1029
// on how long the client program wants to hold on to
1030
// the Connection object.
1031
tr.clearLcc();
1032                        tr.cleanupOnError(e);
1033
1034                    } catch (Throwable JavaDoc t) {
1035                        throw handleException(t);
1036                    } finally {
1037                        restoreContextStack();
1038                    }
1039                }
1040            }
1041
1042            if (!isClosed())
1043                setInactive();
1044        }
1045    }
1046
1047    /**
1048     * Tests to see if a Connection is closed.
1049     *
1050     * @return true if the connection is closed; false if it's still open
1051     */

1052    public final boolean isClosed() {
1053        if (active) {
1054
1055            // I am attached, check the database state
1056
if (getTR().isActive()) {
1057                return false;
1058            }
1059
1060            setInactive();
1061
1062        }
1063        return true;
1064    }
1065
1066    /**
1067     * A Connection's database is able to provide information
1068     * describing its tables, its supported SQL grammar, its stored
1069     * procedures, the capabilities of this connection, etc. This
1070     * information is made available through a DatabaseMetaData
1071     * object.
1072     *
1073     * @return a DatabaseMetaData object for this Connection
1074     * @exception SQLException if a database-access error occurs.
1075     */

1076    public DatabaseMetaData JavaDoc getMetaData() throws SQLException JavaDoc {
1077        checkIfClosed();
1078
1079        if (dbMetadata == null) {
1080
1081            // There is a case where dbname can be null.
1082
// Replication client of this method does not have a
1083
// JDBC connection; therefore dbname is null and this
1084
// is expected.
1085
//
1086
dbMetadata = factory.newEmbedDatabaseMetaData(this, getTR().getUrl());
1087        }
1088        return dbMetadata;
1089    }
1090
1091    /**
1092        JDBC 3.0
1093     * Retrieves the current holdability of ResultSet objects created using this
1094     * Connection object.
1095     *
1096     *
1097     * @return The holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
1098     * or ResultSet.CLOSE_CURSORS_AT_COMMIT
1099     *
1100     */

1101    public final int getHoldability() throws SQLException JavaDoc {
1102        checkIfClosed();
1103        return connectionHoldAbility;
1104    }
1105
1106    /**
1107        JDBC 3.0
1108     * Changes the holdability of ResultSet objects created using this
1109     * Connection object to the given holdability.
1110     *
1111     *
1112     * @param holdability A ResultSet holdability constant, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
1113     * or ResultSet.CLOSE_CURSORS_AT_COMMIT
1114     *
1115     */

1116    public final void setHoldability(int holdability) throws SQLException JavaDoc {
1117        checkIfClosed();
1118        connectionHoldAbility = holdability;
1119    }
1120
1121    /**
1122     * You can put a connection in read-only mode as a hint to enable
1123     * database optimizations.
1124     *
1125     * <P><B>Note:</B> setReadOnly cannot be called while in the
1126     * middle of a transaction.
1127     *
1128     * @param readOnly true enables read-only mode; false disables
1129     * read-only mode.
1130     * @exception SQLException if a database-access error occurs.
1131     */

1132    public final void setReadOnly(boolean readOnly) throws SQLException JavaDoc
1133    {
1134        synchronized(getConnectionSynchronization())
1135        {
1136                        setupContextStack();
1137            try {
1138                getLanguageConnection().setReadOnly(readOnly);
1139            } catch (StandardException e) {
1140                throw handleException(e);
1141            } finally {
1142                restoreContextStack();
1143            }
1144        }
1145    }
1146
1147    /**
1148     * Tests to see if the connection is in read-only mode.
1149     *
1150     * @return true if connection is read-only
1151     * @exception SQLException if a database-access error occurs.
1152     */

1153    public final boolean isReadOnly() throws SQLException JavaDoc
1154    {
1155        checkIfClosed();
1156        return getLanguageConnection().isReadOnly();
1157    }
1158
1159    /**
1160     * A sub-space of this Connection's database may be selected by setting a
1161     * catalog name. If the driver does not support catalogs it will
1162     * silently ignore this request.
1163     *
1164     * @exception SQLException if a database-access error occurs.
1165     */

1166    public void setCatalog(String JavaDoc catalog) throws SQLException JavaDoc {
1167        checkIfClosed();
1168        // silently ignoring this request like the javadoc said.
1169
return;
1170    }
1171
1172    /**
1173     * Return the Connection's current catalog name.
1174     *
1175     * @return the current catalog name or null
1176     * @exception SQLException if a database-access error occurs.
1177     */

1178    public String JavaDoc getCatalog() throws SQLException JavaDoc {
1179        checkIfClosed();
1180        // we do not have support for Catalog, just return null as
1181
// the JDBC specs mentions then.
1182
return null;
1183    }
1184
1185    /**
1186     * You can call this method to try to change the transaction
1187     * isolation level using one of the TRANSACTION_* values.
1188     *
1189     * <P><B>Note:</B> setTransactionIsolation causes the current
1190     * transaction to commit
1191     *
1192     * @param level one of the TRANSACTION_* isolation values with the
1193     * exception of TRANSACTION_NONE; some databases may not support
1194     * other values
1195     * @exception SQLException if a database-access error occurs.
1196     * @see DatabaseMetaData#supportsTransactionIsolationLevel
1197     */

1198    public void setTransactionIsolation(int level) throws SQLException JavaDoc {
1199
1200        if (level == getTransactionIsolation())
1201            return;
1202
1203        // Convert the isolation level to the internal one
1204
int iLevel;
1205        switch (level)
1206        {
1207        case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
1208            iLevel = ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL;
1209            break;
1210
1211        case java.sql.Connection.TRANSACTION_READ_COMMITTED:
1212            iLevel = ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL;
1213            break;
1214
1215        case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
1216            iLevel = ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL;
1217            break;
1218
1219        case java.sql.Connection.TRANSACTION_SERIALIZABLE:
1220            iLevel = ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL;
1221            break;
1222        default:
1223            throw newSQLException(SQLState.UNIMPLEMENTED_ISOLATION_LEVEL, new Integer JavaDoc(level));
1224        }
1225
1226        synchronized(getConnectionSynchronization())
1227        {
1228            setupContextStack();
1229            try {
1230                getLanguageConnection().setIsolationLevel(iLevel);
1231            } catch (StandardException e) {
1232                throw handleException(e);
1233            } finally {
1234                restoreContextStack();
1235            }
1236        }
1237    }
1238
1239
1240    /**
1241     * Get this Connection's current transaction isolation mode.
1242     *
1243     * @return the current TRANSACTION_* mode value
1244     * @exception SQLException if a database-access error occurs.
1245     */

1246    public final int getTransactionIsolation() throws SQLException JavaDoc {
1247        checkIfClosed();
1248        return ExecutionContext.CS_TO_JDBC_ISOLATION_LEVEL_MAP[getLanguageConnection().getCurrentIsolationLevel()];
1249    }
1250
1251    /**
1252     * The first warning reported by calls on this Connection is
1253     * returned.
1254     *
1255     * <P><B>Note:</B> Subsequent warnings will be chained to this
1256     * SQLWarning.
1257     *
1258     * @return the first SQLWarning or null
1259     *
1260     * Synchronization note: Warnings are synchronized
1261     * on nesting level
1262     */

1263    public final synchronized SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc {
1264        checkIfClosed();
1265        return topWarning;
1266    }
1267
1268    /**
1269     * After this call, getWarnings returns null until a new warning is
1270     * reported for this Connection.
1271     *
1272     * Synchronization node: Warnings are synchonized
1273     * on nesting level
1274     */

1275    public final synchronized void clearWarnings() throws SQLException JavaDoc {
1276        checkIfClosed();
1277        topWarning = null;
1278    }
1279
1280    /////////////////////////////////////////////////////////////////////////
1281
//
1282
// JDBC 2.0 - New public methods
1283
//
1284
/////////////////////////////////////////////////////////////////////////
1285

1286    /**
1287     *
1288     * Get the type-map object associated with this connection.
1289     * By default, the map returned is empty.
1290     * JDBC 2.0 - java.util.Map requires JDK 1
1291     *
1292     */

1293    public java.util.Map JavaDoc getTypeMap() throws SQLException JavaDoc {
1294        checkIfClosed();
1295        // just return an immuntable empty map
1296
return java.util.Collections.EMPTY_MAP;
1297    }
1298
1299    /**
1300     * Install a type-map object as the default type-map for
1301     * this connection.
1302     * JDBC 2.0 - java.util.Map requires JDK 1
1303     *
1304     * @exception SQLException Feature not implemented for now.
1305     */

1306    public final void setTypeMap(java.util.Map JavaDoc map) throws SQLException JavaDoc {
1307        checkIfClosed();
1308        if( map == null)
1309            throw Util.generateCsSQLException(SQLState.INVALID_API_PARAMETER,map,"map",
1310                                              "java.sql.Connection.setTypeMap");
1311        if(!(map.isEmpty()))
1312            throw Util.notImplemented();
1313    }
1314
1315    /////////////////////////////////////////////////////////////////////////
1316
//
1317
// Implementation specific methods
1318
//
1319
/////////////////////////////////////////////////////////////////////////
1320

1321    /**
1322        Add a warning to the current list of warnings, to follow
1323        this note from Connection.getWarnings.
1324        Note: Subsequent warnings will be chained to this SQLWarning.
1325
1326        @see java.sql.Connection#getWarnings
1327    */

1328     public final synchronized void addWarning(SQLWarning JavaDoc newWarning) {
1329        if (topWarning == null) {
1330            topWarning = newWarning;
1331            return;
1332        }
1333
1334        topWarning.setNextWarning(newWarning);
1335    }
1336
1337    /**
1338     * Return the dbname for this connection.
1339     *
1340     * @return String The dbname for this connection.
1341     */

1342    public String JavaDoc getDBName()
1343    {
1344        if (SanityManager.DEBUG)
1345            SanityManager.ASSERT(!isClosed(), "connection is closed");
1346
1347        return getTR().getDBName();
1348    }
1349
1350    public final LanguageConnectionContext getLanguageConnection() {
1351
1352        if (SanityManager.DEBUG)
1353            SanityManager.ASSERT(!isClosed(), "connection is closed");
1354
1355        return getTR().getLcc();
1356    }
1357
1358    /**
1359     * Raises an exception if the connection is closed.
1360     *
1361     * @exception SQLException if the connection is closed
1362     */

1363    protected final void checkIfClosed() throws SQLException JavaDoc {
1364        if (isClosed()) {
1365            throw Util.noCurrentConnection();
1366        }
1367    }
1368
1369    //EmbedConnection30 overrides this method so it can release the savepoints array if
1370
//the exception severity is transaction level
1371
SQLException JavaDoc handleException(Throwable JavaDoc thrownException)
1372            throws SQLException JavaDoc
1373    {
1374        /*
1375        ** By default, rollback the connection on if autocommit
1376        ** is on.
1377        */

1378        return getTR().handleException(thrownException,
1379                                  autoCommit,
1380                                  true // Rollback xact on auto commit
1381
);
1382    }
1383
1384    /**
1385        Handle any type of Exception.
1386        <UL>
1387        <LI> Inform the contexts of the error
1388        <LI> Throw an Util based upon the thrown exception.
1389        </UL>
1390
1391        REMIND: now that we know all the exceptions from our driver
1392        are Utils, would it make sense to shut down the system
1393        for unknown SQLExceptions? At present, we do not.
1394
1395        Because this is the last stop for exceptions,
1396        it will catch anything that occurs in it and try
1397        to cleanup before re-throwing them.
1398    
1399        @param thrownException the exception
1400        @param rollbackOnAutoCommit rollback the xact on if autocommit is
1401                on, otherwise rollback stmt but leave xact open (and
1402                continue to hold on to locks). Most of the time, this
1403                will be true, excepting operations on result sets, like
1404                getInt().
1405    */

1406    final SQLException JavaDoc handleException(Throwable JavaDoc thrownException,
1407                                       boolean rollbackOnAutoCommit)
1408            throws SQLException JavaDoc
1409    {
1410        return getTR().handleException(thrownException, autoCommit,
1411                                  rollbackOnAutoCommit);
1412
1413    }
1414
1415    /*
1416       This is called from the EmbedConnectionContext to
1417       close on errors. We assume all handling of the connectin
1418       is dealt with via the context stack, and our only role
1419       is to mark ourself as closed.
1420     */

1421
1422    /**
1423        Close the connection when processing errors, or when
1424        closing a nested connection.
1425        <p>
1426        This only marks it as closed and frees up its resources;
1427        any closing of the underlying connection or commit work
1428        is assumed to be done elsewhere.
1429
1430        Called from EmbedConnectionContext's cleanup routine,
1431        and by proxy.close().
1432     */

1433
1434    public final void setInactive() {
1435
1436        if (active == false)
1437            return;
1438        // active = false
1439
// tr = null !-> active = false
1440

1441        synchronized (getConnectionSynchronization()) {
1442            active = false;
1443            // tr = null; cleanupOnerror sets inactive but still needs tr to
1444
// restore context later
1445
dbMetadata = null;
1446        }
1447    }
1448
1449    /**
1450        @exception Throwable standard error policy
1451     */

1452    protected void finalize() throws Throwable JavaDoc
1453    {
1454        if (rootConnection == this)
1455        {
1456            super.finalize();
1457            if (!isClosed())
1458                close(exceptionClose);
1459        }
1460    }
1461
1462    /**
1463     * if auto commit is on, remember that we need to commit
1464     * the current statement.
1465     */

1466    protected void needCommit() {
1467        if (!needCommit) needCommit = true;
1468    }
1469
1470    /**
1471     * if a commit is needed, perform it.
1472     *
1473     * Must have connection synchonization and context set up already.
1474     *
1475     * @exception SQLException if commit returns error
1476     */

1477    protected void commitIfNeeded() throws SQLException JavaDoc
1478    {
1479        if (autoCommit && needCommit)
1480        {
1481            try
1482            {
1483                getTR().commit();
1484            }
1485            catch (Throwable JavaDoc t)
1486            {
1487                throw handleException(t);
1488            }
1489            needCommit = false;
1490        }
1491    }
1492
1493    /**
1494     * If in autocommit, then commit.
1495     *
1496     * Used to force a commit after a result set closes in autocommit mode.
1497     * The needCommit mechanism does not work correctly as there are times
1498     * with cursors (like a commit, followed by a next, followed by a close)
1499     * where the system does not think it needs a commit but we need to
1500     * force the commit on close. It seemed safer to just force a commit
1501     * on close rather than count on keeping the needCommit flag correct for
1502     * all cursor cases.
1503     *
1504     * Must have connection synchonization and context set up already.
1505     *
1506     * @exception SQLException if commit returns error
1507     */

1508    protected void commitIfAutoCommit() throws SQLException JavaDoc
1509    {
1510        if (autoCommit)
1511        {
1512            try
1513            {
1514                getTR().commit();
1515            }
1516            catch (Throwable JavaDoc t)
1517            {
1518                throw handleException(t);
1519            }
1520            needCommit = false;
1521        }
1522    }
1523
1524
1525    final protected Object JavaDoc getConnectionSynchronization()
1526  {
1527        return rootConnection;
1528  }
1529
1530    /**
1531        Install the context manager for this thread. Check connection status here.
1532        @exception SQLException if fails
1533     */

1534    protected final void setupContextStack() throws SQLException JavaDoc {
1535
1536        /*
1537            Track this entry, then throw an exception
1538            rather than doing the quiet return. Need the
1539            track before the throw because the backtrack
1540            is in a finally block.
1541         */

1542
1543        checkIfClosed();
1544
1545        getTR().setupContextStack();
1546
1547    }
1548
1549    protected final void restoreContextStack() throws SQLException JavaDoc {
1550
1551        if (SanityManager.DEBUG)
1552        Util.ASSERT(this, (active) || getTR().getCsf() !=null, "No context service to do restore");
1553
1554        TransactionResourceImpl tr = getTR();
1555
1556        //REMIND: someone is leaving an incorrect manager on when they
1557
// are exiting the system in the nested case.
1558
if (SanityManager.DEBUG)
1559        {
1560            if ((tr.getCsf() != null) && (tr.getCsf().getCurrentContextManager() !=
1561                tr.getContextManager()))
1562            {
1563                Util.THROWASSERT(this,
1564                    "Current Context Manager not the one was expected: " +
1565                     tr.getCsf().getCurrentContextManager() + " " +
1566                     tr.getContextManager());
1567            }
1568        }
1569
1570        tr.restoreContextStack();
1571    }
1572
1573    /*
1574    ** Create database methods.
1575    */

1576
1577    /**
1578        Create a new database.
1579        @param dbname the database name
1580        @param info the properties
1581
1582        @return Database The newly created database or null.
1583
1584        @exception SQLException if fails to create database
1585    */

1586
1587    private Database createDatabase(String JavaDoc dbname, Properties JavaDoc info)
1588        throws SQLException JavaDoc {
1589
1590        info = filterProperties(info);
1591
1592        try {
1593            if (Monitor.createPersistentService(Property.DATABASE_MODULE, dbname, info) == null)
1594            {
1595                // service already exists, create a warning
1596
addWarning(EmbedSQLWarning.newEmbedSQLWarning(SQLState.DATABASE_EXISTS, dbname));
1597            }
1598        } catch (StandardException mse) {
1599
1600            SQLException JavaDoc se = newSQLException(SQLState.CREATE_DATABASE_FAILED, dbname);
1601            se.setNextException(handleException(mse));
1602            throw se;
1603        }
1604
1605        // clear these values as some modules hang onto
1606
// the properties set corresponding to service.properties
1607
// and they shouldn't be interested in these JDBC attributes.
1608
info.clear();
1609
1610        return (Database) Monitor.findService(Property.DATABASE_MODULE, dbname);
1611    }
1612
1613
1614    /**
1615        Return false iff the monitor cannot handle a service
1616        of the type indicated by the protocol within the name.
1617        If that's the case then we are the wrong driver.
1618
1619        Throw exception if anything else is wrong.
1620     */

1621
1622    private boolean bootDatabase(Properties JavaDoc info) throws Throwable JavaDoc
1623    {
1624        String JavaDoc dbname = tr.getDBName();
1625
1626        // boot database now
1627
try {
1628
1629            info = filterProperties(info);
1630            
1631            // try to start the service if it doesn't already exist
1632
if (!Monitor.startPersistentService(dbname, info)) {
1633                // a false indicates the monitor cannot handle a service
1634
// of the type indicated by the protocol within the name.
1635
// If that's the case then we are the wrong driver
1636
// so just return null.
1637
return false;
1638            }
1639
1640            // clear these values as some modules hang onto
1641
// the properties set corresponding to service.properties
1642
// and they shouldn't be interested in these JDBC attributes.
1643
info.clear();
1644
1645            Database database = (Database) Monitor.findService(Property.DATABASE_MODULE, dbname);
1646            tr.setDatabase(database);
1647
1648        } catch (StandardException mse) {
1649            SQLException JavaDoc se = newSQLException(SQLState.BOOT_DATABASE_FAILED, dbname);
1650
1651            Throwable JavaDoc ne = mse.getNestedException();
1652            SQLException JavaDoc nse;
1653
1654            /*
1655              If there is a next exception, assume
1656              that the first one is just a redundant "see the
1657              next exception" message.
1658              if it is a BEI, treat it as a database exception.
1659              If there isn't a BEI, treat it as a java exception.
1660
1661              In general we probably want to walk the chain
1662              and return all of them, but empirically, this
1663              is all we need to do for now.
1664              */

1665            if (ne instanceof StandardException)
1666                nse = Util.generateCsSQLException((StandardException)ne);
1667            else if (ne != null)
1668                nse = Util.javaException(ne);
1669            else
1670                nse = Util.generateCsSQLException(mse);
1671
1672            se.setNextException(nse);
1673            throw se;
1674        }
1675
1676        // If database exists, getDatabase() will return the database object.
1677
// If any error occured while booting an existing database, an
1678
// exception would have been thrown already.
1679
return true;
1680
1681    }
1682
1683    /*
1684     * Class interface methods used by database metadata to ensure
1685     * good relations with autocommit.
1686     */

1687
1688    PreparedStatement JavaDoc prepareMetaDataStatement(String JavaDoc sql)
1689        throws SQLException JavaDoc {
1690        synchronized (getConnectionSynchronization()) {
1691                        setupContextStack();
1692            PreparedStatement JavaDoc s = null;
1693            try {
1694                s = factory.newEmbedPreparedStatement(this, sql, true,
1695                                              JDBC20Translation.TYPE_FORWARD_ONLY,
1696                                              JDBC20Translation.CONCUR_READ_ONLY,
1697                                              connectionHoldAbility,
1698                                              JDBC30Translation.NO_GENERATED_KEYS,
1699                                              null,
1700                                              null);
1701            } finally {
1702                restoreContextStack();
1703            }
1704            return s;
1705        }
1706    }
1707
1708    public final InternalDriver getLocalDriver()
1709    {
1710        if (SanityManager.DEBUG)
1711            SanityManager.ASSERT(!isClosed(), "connection is closed");
1712
1713        return getTR().getDriver();
1714    }
1715
1716    /**
1717        Return the context manager for this connection.
1718    */

1719    public final ContextManager getContextManager() {
1720
1721        if (SanityManager.DEBUG)
1722            SanityManager.ASSERT(!isClosed(), "connection is closed");
1723
1724        return getTR().getContextManager();
1725    }
1726
1727    /**
1728     * Filter out properties from the passed in set of JDBC attributes
1729     * to remove any derby.* properties. This is to ensure that setting
1730     * derby.* properties does not work this way, it's not a defined way
1731     * to set such properties and could be a secuirty hole in allowing
1732     * remote connections to override system, application or database settings.
1733     *
1734     * @return a new Properties set copied from the parameter but with no
1735     * derby.* properties.
1736     */

1737    private Properties JavaDoc filterProperties(Properties JavaDoc inputSet) {
1738        Properties JavaDoc limited = new Properties JavaDoc();
1739
1740        // filter out any derby.* properties, only
1741
// JDBC attributes can be set this way
1742
for (java.util.Enumeration JavaDoc e = inputSet.propertyNames(); e.hasMoreElements(); ) {
1743
1744            String JavaDoc key = (String JavaDoc) e.nextElement();
1745
1746            // we don't allow properties to be set this way
1747
if (key.startsWith("derby."))
1748                continue;
1749            limited.put(key, inputSet.getProperty(key));
1750        }
1751        return limited;
1752    }
1753
1754    /*
1755    ** methods to be overridden by subimplementations wishing to insert
1756    ** their classes into the mix.
1757    */

1758
1759    protected Database getDatabase()
1760    {
1761        if (SanityManager.DEBUG)
1762            SanityManager.ASSERT(!isClosed(), "connection is closed");
1763
1764        return getTR().getDatabase();
1765    }
1766
1767    final protected TransactionResourceImpl getTR()
1768    {
1769        return rootConnection.tr;
1770    }
1771
1772    private EmbedConnectionContext pushConnectionContext(ContextManager cm) {
1773        return new EmbedConnectionContext(cm, this);
1774    }
1775
1776    public final void setApplicationConnection(java.sql.Connection JavaDoc applicationConnection) {
1777        this.applicationConnection = applicationConnection;
1778    }
1779
1780    public final java.sql.Connection JavaDoc getApplicationConnection() {
1781        return applicationConnection;
1782    }
1783
1784    public void setDrdaID(String JavaDoc drdaID) {
1785        getLanguageConnection().setDrdaID(drdaID);
1786    }
1787
1788    /**
1789        Reset the connection before it is returned from a PooledConnection
1790        to a new application request (wrapped by a BrokeredConnection).
1791        Examples of reset covered here is dropping session temporary tables
1792        and reseting IDENTITY_VAL_LOCAL.
1793        Most JDBC level reset is handled by calling standard java.sql.Connection
1794        methods from EmbedPooledConnection.
1795     */

1796    public void resetFromPool() throws SQLException JavaDoc {
1797        synchronized (getConnectionSynchronization())
1798        {
1799            setupContextStack();
1800            try {
1801                getLanguageConnection().resetFromPool();
1802            } catch (StandardException t) {
1803                throw handleException(t);
1804            }
1805            finally
1806            {
1807                restoreContextStack();
1808            }
1809        }
1810    }
1811
1812    /*
1813    ** methods to be overridden by subimplementations wishing to insert
1814    ** their classes into the mix.
1815    ** The reason we need to override them is because we want to create a
1816    ** Local20/LocalStatment object (etc) rather than a Local/LocalStatment
1817    ** object (etc).
1818    */

1819
1820
1821    /*
1822    ** XA support
1823    */

1824
1825    public final int xa_prepare() throws SQLException JavaDoc {
1826
1827        synchronized (getConnectionSynchronization())
1828        {
1829            setupContextStack();
1830            try
1831            {
1832                XATransactionController tc =
1833                    (XATransactionController) getLanguageConnection().getTransactionExecute();
1834
1835                int ret = tc.xa_prepare();
1836
1837                if (ret == XATransactionController.XA_RDONLY)
1838                {
1839                    // On a prepare call, xa allows an optimization that if the
1840
// transaction is read only, the RM can just go ahead and
1841
// commit it. So if store returns this read only status -
1842
// meaning store has taken the liberty to commit already - we
1843
// needs to turn around and call internalCommit (without
1844
// committing the store again) to make sure the state is
1845
// consistent. Since the transaction is read only, there is
1846
// probably not much that needs to be done.
1847

1848                    getLanguageConnection().internalCommit(false /* don't commitStore again */);
1849                }
1850                return ret;
1851            } catch (StandardException t)
1852            {
1853                throw handleException(t);
1854            }
1855            finally
1856            {
1857                restoreContextStack();
1858            }
1859        }
1860    }
1861
1862
1863    public final void xa_commit(boolean onePhase) throws SQLException JavaDoc {
1864
1865        synchronized (getConnectionSynchronization())
1866        {
1867            setupContextStack();
1868            try
1869            {
1870                getLanguageConnection().xaCommit(onePhase);
1871            } catch (StandardException t)
1872            {
1873                throw handleException(t);
1874            }
1875            finally
1876            {
1877                restoreContextStack();
1878            }
1879        }
1880    }
1881    public final void xa_rollback() throws SQLException JavaDoc {
1882
1883        synchronized (getConnectionSynchronization())
1884        {
1885            setupContextStack();
1886            try
1887            {
1888                getLanguageConnection().xaRollback();
1889            } catch (StandardException t)
1890            {
1891                throw handleException(t);
1892            }
1893            finally
1894            {
1895                restoreContextStack();
1896            }
1897        }
1898    }
1899    /**
1900     * returns false if there is an underlying transaction and that transaction
1901     * has done work. True if there is no underlying transaction or that
1902     * underlying transaction is idle
1903     */

1904    public final boolean transactionIsIdle()
1905    {
1906        return getTR().isIdle();
1907    }
1908    private int setResultSetType(int resultSetType) {
1909
1910        /* Add warning if scroll sensitive cursor
1911         * and downgrade to scroll insensitive cursor.
1912         */

1913        if (resultSetType == JDBC20Translation.TYPE_SCROLL_SENSITIVE)
1914        {
1915            addWarning(EmbedSQLWarning.newEmbedSQLWarning(SQLState.NO_SCROLL_SENSITIVE_CURSORS));
1916            resultSetType = JDBC20Translation.TYPE_SCROLL_INSENSITIVE;
1917        }
1918        return resultSetType;
1919    }
1920    
1921
1922    /**
1923     * Set the transaction isolation level that will be used for the
1924     * next prepare. Used by network server to implement DB2 style
1925     * isolation levels.
1926     * @param level Isolation level to change to. level is the DB2 level
1927     * specified in the package names which happen to correspond
1928     * to our internal levels. If
1929     * level == ExecutionContext.UNSPECIFIED_ISOLATION,
1930     * the statement won't be prepared with an isolation level.
1931     *
1932     *
1933     */

1934    public void setPrepareIsolation(int level) throws SQLException JavaDoc
1935    {
1936        if (level == getPrepareIsolation())
1937            return;
1938
1939        switch (level)
1940        {
1941            case ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL:
1942            case ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL:
1943            case ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL:
1944            case ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL:
1945            case ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL:
1946                break;
1947            default:
1948                throw Util.generateCsSQLException(
1949                                                               SQLState.UNIMPLEMENTED_ISOLATION_LEVEL, new Integer JavaDoc(level));
1950        }
1951        
1952        synchronized(getConnectionSynchronization())
1953        {
1954            getLanguageConnection().setPrepareIsolationLevel(level);
1955        }
1956    }
1957
1958    /**
1959     * Return prepare isolation
1960     */

1961    public int getPrepareIsolation()
1962    {
1963        return getLanguageConnection().getPrepareIsolationLevel();
1964    }
1965
1966    /**
1967        Return a unique order number for a result set.
1968        A unique value is only needed if the result set is
1969        being created within procedure and thus must be using
1970        a nested connection.
1971    */

1972    final int getResultSetOrderId() {
1973
1974        if (this == rootConnection) {
1975            return 0;
1976        } else {
1977            return rootConnection.resultSetId++;
1978        }
1979    }
1980
1981    protected SQLException JavaDoc newSQLException(String JavaDoc messageId) {
1982        return Util.generateCsSQLException(messageId);
1983    }
1984    protected SQLException JavaDoc newSQLException(String JavaDoc messageId, Object JavaDoc arg1) {
1985        return Util.generateCsSQLException(messageId, arg1);
1986    }
1987    protected SQLException JavaDoc newSQLException(String JavaDoc messageId, Object JavaDoc arg1, Object JavaDoc arg2) {
1988        return Util.generateCsSQLException(messageId, arg1, arg2);
1989    }
1990
1991    /////////////////////////////////////////////////////////////////////////
1992
//
1993
// OBJECT OVERLOADS
1994
//
1995
/////////////////////////////////////////////////////////////////////////
1996

1997    /**
1998     * Get a String representation that uniquely identifies
1999     * this connection. Include the same information that is
2000     * printed in the log for various trace and error messages.
2001     *
2002     * In Derby the "physical" connection is a LanguageConnectionContext,
2003     * or LCC.
2004     * The JDBC Connection is an JDBC-specific layer on top of this. Rather
2005     * than create a new id here, we simply use the id of the underlying LCC.
2006     * Note that this is a big aid in debugging, because much of the
2007     * engine trace and log code prints the LCC id.
2008     *
2009     * @return a string representation for this connection
2010     */

2011    public String JavaDoc toString()
2012    {
2013        if ( connString == null )
2014        {
2015            
2016            LanguageConnectionContext lcc = getLanguageConnection();
2017
2018            connString =
2019              this.getClass().getName() + "@" + this.hashCode() + " " +
2020                lcc.xidStr +
2021                    lcc.getTransactionExecute().getTransactionIdString() +
2022                    "), " +
2023                lcc.lccStr +
2024                    Integer.toString(lcc.getInstanceNumber()) + "), " +
2025                lcc.dbnameStr + lcc.getDbname() + "), " +
2026                lcc.drdaStr + lcc.getDrdaID() + ") ";
2027        }
2028        
2029        return connString;
2030    }
2031
2032
2033}
2034
Popular Tags