KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > client > am > Connection


1 /*
2
3    Derby - Class org.apache.derby.client.am.Connection
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.client.am;
23
24 import org.apache.derby.jdbc.ClientBaseDataSource;
25 import org.apache.derby.jdbc.ClientDataSource;
26 import org.apache.derby.shared.common.reference.JDBC30Translation;
27 import org.apache.derby.shared.common.reference.SQLState;
28
29 import java.sql.SQLException JavaDoc;
30
31 public abstract class Connection implements java.sql.Connection JavaDoc,
32         ConnectionCallbackInterface {
33     //---------------------navigational members-----------------------------------
34

35
36     public Agent agent_;
37
38     public DatabaseMetaData databaseMetaData_;
39     // DERBY-210 - WeakHashMap is used to store references to objects to avoid
40
// memory leaks. When there are no other references to the keys in a
41
// WeakHashMap, they will get removed from the map and can thus get
42
// garbage-collected. They do not have to wait till the Connection object
43
// is collected.
44

45     // In Connection.markStatementsClosed() method, this list is traversed to get a
46
// list of open statements, which are marked closed and removed from the list.
47
final java.util.WeakHashMap JavaDoc openStatements_ = new java.util.WeakHashMap JavaDoc();
48
49     // Some statuses of DERBY objects may be invalid on server
50
// after both commit and rollback. For example,
51
// (1) prepared statements need to be re-prepared
52
// after both commit and rollback
53
// (2) result set will be unpositioned on server after both commit and rollback.
54
// If they depend on both commit and rollback, they need to get on CommitAndRollbackListeners_.
55
final java.util.WeakHashMap JavaDoc CommitAndRollbackListeners_ = new java.util.WeakHashMap JavaDoc();
56     private SqlWarning warnings_ = null;
57
58     // ------------------------properties set for life of connection--------------
59

60     // See ClientDataSource pre-connect settings
61
public transient String JavaDoc user_;
62     public boolean retrieveMessageText_;
63     protected boolean jdbcReadOnly_;
64     /**
65      * Holdabilty for created statements.
66      * Only access through the holdability method
67      * to ensure the correct value is returned for an
68      * XA connection.
69      */

70     private int holdability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
71     
72     public String JavaDoc databaseName_;
73
74     // Holds the Product-Specific Identifier which specifies
75
// the product release level of a DDM Server.
76
// The max length is 8.
77
public String JavaDoc productID_;
78
79     // Used to get the public key and encrypt password and/or userid
80
protected EncryptionManager encryptionManager_;
81
82     // used to set transaction isolation level
83
private Statement setTransactionIsolationStmt = null;
84     
85     // used to get transaction isolation level
86
private Statement getTransactionIsolationStmt = null;
87     
88     // ------------------------dynamic properties---------------------------------
89

90     protected boolean open_ = true;
91     protected boolean availableForReuse_ = false;
92
93     public int isolation_ = Configuration.defaultIsolation;
94     public boolean autoCommit_ = true;
95     protected boolean inUnitOfWork_ = false; // This means a transaction is in progress.
96

97     private boolean accumulated440ForMessageProcFailure_ = false;
98     private boolean accumulated444ForMessageProcFailure_ = false;
99     private boolean accumulatedSetReadOnlyWarning_ = false;
100
101
102
103     //---------------------XA-----------------------------------------------------
104

105     protected boolean isXAConnection_ = false; // Indicates an XA connection
106

107     // XA States
108
// The client needs to keep track of the connection's transaction branch association
109
// per table 2.6 in the XA+ specification in order to determine if commits should flow in
110
// autocommit mode. There is no need to keep track of suspended transactions separately from
111
// XA_TO_NOT_ASSOCIATED.
112
//
113
/**
114      * <code>XA_T0_NOT_ASSOCIATED</code>
115      * This connection is not currently associated with an XA transaction
116      * In this state commits will flow in autocommit mode.
117      */

118     public static final int XA_T0_NOT_ASSOCIATED = 0;
119     
120     /**
121      * <code>XA_T1_ASSOCIATED</code>
122      * In this state commits will not flow in autocommit mode.
123      */

124     public static final int XA_T1_ASSOCIATED = 1;
125     
126     //TODO: Remove XA_RECOVER entirely once indoubtlist is gone.
127
//public static final int XA_RECOVER = 14;
128

129
130     private int xaState_ = XA_T0_NOT_ASSOCIATED;
131
132     // XA Host Type
133
public int xaHostVersion_ = 0;
134
135     public int loginTimeout_;
136     public org.apache.derby.jdbc.ClientBaseDataSource dataSource_;
137     public String JavaDoc serverNameIP_;
138     public int portNumber_;
139
140     public java.util.Hashtable JavaDoc clientCursorNameCache_ = new java.util.Hashtable JavaDoc();
141     public boolean canUseCachedConnectBytes_ = false;
142     public int commBufferSize_ = 32767;
143
144     // indicates if a deferred reset connection is required
145
public boolean resetConnectionAtFirstSql_ = false;
146
147     //---------------------constructors/finalizer---------------------------------
148

149     // For jdbc 2 connections
150
protected Connection(org.apache.derby.client.am.LogWriter logWriter,
151                          String JavaDoc user,
152                          String JavaDoc password,
153                          org.apache.derby.jdbc.ClientBaseDataSource dataSource)
154                                                            throws SqlException {
155         initConnection(logWriter, user, dataSource);
156     }
157
158     protected Connection(org.apache.derby.client.am.LogWriter logWriter,
159                          String JavaDoc user,
160                          String JavaDoc password,
161                          boolean isXAConn,
162                          org.apache.derby.jdbc.ClientBaseDataSource dataSource)
163                                                            throws SqlException {
164         isXAConnection_ = isXAConn;
165         initConnection(logWriter, user, dataSource);
166     }
167
168     // For jdbc 2 connections
169
protected void initConnection(org.apache.derby.client.am.LogWriter logWriter,
170                                   String JavaDoc user,
171                                   org.apache.derby.jdbc.ClientBaseDataSource
172                                             dataSource) throws SqlException {
173         if (logWriter != null) {
174             logWriter.traceConnectEntry(dataSource);
175         }
176
177         user_ = user;
178
179         // Extract common properties.
180
// Derby-409 fix - Append connectionAttributes only if it is non-null.
181
// DERBY-1130 - Append connectionAttributes only if database name is
182
// non-null. This will prevent use of database name set using
183
// "setConnectionAttributes" method.
184
databaseName_ = dataSource.getDatabaseName();
185         String JavaDoc connAtrrs = dataSource.getConnectionAttributes();
186         if(databaseName_ != null && connAtrrs != null)
187             databaseName_ = databaseName_ + ";" + connAtrrs;
188
189         retrieveMessageText_ = dataSource.getRetrieveMessageText();
190
191         loginTimeout_ = dataSource.getLoginTimeout();
192         dataSource_ = dataSource;
193
194         serverNameIP_ = dataSource.getServerName();
195         portNumber_ = dataSource.getPortNumber();
196
197
198         agent_ = newAgent_(logWriter,
199                 loginTimeout_,
200                 serverNameIP_,
201                 portNumber_);
202     }
203
204     // For jdbc 2 connections
205
protected Connection(org.apache.derby.client.am.LogWriter logWriter,
206                          boolean isXAConn,
207                          org.apache.derby.jdbc.ClientBaseDataSource dataSource)
208                                                             throws SqlException {
209         if (logWriter != null) {
210             logWriter.traceConnectEntry(dataSource);
211         }
212         isXAConnection_ = isXAConn;
213
214         user_ = ClientDataSource.propertyDefault_user;
215
216         // Extract common properties.
217
databaseName_ = dataSource.getDatabaseName();
218         retrieveMessageText_ = dataSource.getRetrieveMessageText();
219
220         loginTimeout_ = dataSource.getLoginTimeout();
221         dataSource_ = dataSource;
222
223         serverNameIP_ = dataSource.getServerName();
224         portNumber_ = dataSource.getPortNumber();
225
226
227         agent_ = newAgent_(logWriter,
228                 loginTimeout_,
229                 serverNameIP_,
230                 portNumber_);
231     }
232
233     // This is a callback method, called by subsystem - NetConnection
234
protected void resetConnection(LogWriter logWriter,
235                                    String JavaDoc user,
236                                    ClientBaseDataSource ds,
237                                    boolean recomputeFromDataSource) throws SqlException {
238         // clearWarningsX() will re-initialize the following properties
239
clearWarningsX();
240
241         user_ = (user != null) ? user : user_;
242
243         if (ds != null && recomputeFromDataSource) { // no need to reinitialize connection state if ds hasn't changed
244
user_ = (user != null) ? user : ds.getUser();
245             ;
246
247             retrieveMessageText_ = ds.getRetrieveMessageText();
248
249
250             // property encryptionManager_
251
// if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
252
encryptionManager_ = null;
253
254             // property: open_
255
// this should already be true
256

257             isolation_ = Configuration.defaultIsolation;
258             autoCommit_ = true;
259             inUnitOfWork_ = false;
260
261             loginTimeout_ = ds.getLoginTimeout();
262             dataSource_ = ds;
263             
264             holdability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
265         }
266
267         
268         if (recomputeFromDataSource) {
269             this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
270         }
271     }
272
273     protected void resetConnection(LogWriter logWriter,
274                                    String JavaDoc databaseName,
275                                    java.util.Properties JavaDoc properties) throws SqlException {
276         // clearWarningsX() will re-initialize the following properties
277
// warnings_, accumulated440ForMessageProcFailure_,
278
// accumulated444ForMessageProcFailure_, and accumulatedSetReadOnlyWarning_
279
clearWarningsX();
280
281         databaseName_ = databaseName;
282         user_ = ClientDataSource.getUser(properties);
283
284         retrieveMessageText_ = ClientDataSource.getRetrieveMessageText(properties);
285
286
287         // property encryptionManager_
288
// if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
289
encryptionManager_ = null;
290
291         // property: open_
292
// this should already be true
293

294         isolation_ = Configuration.defaultIsolation;
295         autoCommit_ = true;
296         inUnitOfWork_ = false;
297
298         this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
299
300     }
301
302
303     // For jdbc 1 connections
304
protected Connection(LogWriter logWriter,
305                          int driverManagerLoginTimeout,
306                          String JavaDoc serverName,
307                          int portNumber,
308                          String JavaDoc databaseName,
309                          java.util.Properties JavaDoc properties) throws SqlException {
310         if (logWriter != null) {
311             logWriter.traceConnectEntry(serverName, portNumber, databaseName, properties);
312         }
313
314         databaseName_ = databaseName;
315
316         // Extract common properties.
317
user_ = ClientDataSource.getUser(properties);
318         retrieveMessageText_ = ClientDataSource.getRetrieveMessageText(properties);
319
320         loginTimeout_ = driverManagerLoginTimeout;
321         serverNameIP_ = serverName;
322         portNumber_ = portNumber;
323
324         agent_ = newAgent_(logWriter,
325                 loginTimeout_,
326                 serverNameIP_,
327                 portNumber_);
328     }
329
330     // Users are advised to call the method close() on Statement and Connection objects when they are done with them.
331
// However, some users will forget, and some code may get killed before it can close these objects.
332
// Therefore, if JDBC drivers have state associated with JDBC objects that need to get
333
// explicitly cleared up, they should provide finalize methods to take care of them.
334
// The garbage collector will call these finalize methods when the objects are found to be garbage,
335
// and this will give the driver a chance to close (or otherwise clean up) the objects.
336
// Note, however, that there is no guarantee that the garbage collector will ever run.
337
// If that is the case, the finalizers will not be called.
338
protected void finalize() throws java.lang.Throwable JavaDoc {
339         if (agent_.loggingEnabled()) {
340             agent_.logWriter_.traceEntry(this, "finalize");
341         }
342
343         // finalize() differs from close() in that it will not throw an
344
// exception if a transaction is in progress.
345
// finalize() also differs from close() in that it will not drive
346
// an auto-commit before disconnecting.
347
//
348
// If a transaction is in progress, a close() request will throw an SqlException.
349
// However, if a connection with an incomplete transaction is finalized,
350
// or is abruptly terminated by application exit,
351
// the normal rollback semantics imposed by the DERBY server are adopted.
352
// So we just pull the plug and let the server handle this default semantic.
353

354         if (!open_) {
355             return;
356         }
357         agent_.disconnectEvent();
358         super.finalize();
359     }
360
361     // ---------------------------jdbc 1------------------------------------------
362

363     synchronized public java.sql.Statement JavaDoc createStatement() throws SQLException JavaDoc {
364         try
365         {
366             if (agent_.loggingEnabled()) {
367                 agent_.logWriter_.traceEntry(this, "createStatement");
368             }
369             Statement s = createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
370             if (agent_.loggingEnabled()) {
371                 agent_.logWriter_.traceExit(this, "createStatement", s);
372             }
373             return s;
374         }
375         catch ( SqlException se )
376         {
377             throw se.getSQLException();
378         }
379     }
380
381     synchronized public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql) throws SQLException JavaDoc {
382         try
383         {
384             if (agent_.loggingEnabled()) {
385                 agent_.logWriter_.traceEntry(this, "prepareStatement", sql);
386             }
387             PreparedStatement ps = prepareStatementX(sql,
388                     java.sql.ResultSet.TYPE_FORWARD_ONLY,
389                     java.sql.ResultSet.CONCUR_READ_ONLY,
390                     holdability(),
391                     java.sql.Statement.NO_GENERATED_KEYS,
392                     null);
393             if (agent_.loggingEnabled()) {
394                 agent_.logWriter_.traceExit(this, "prepareStatement", ps);
395             }
396             return ps;
397         }
398         catch ( SqlException se )
399         {
400             throw se.getSQLException();
401         }
402     }
403
404     // For internal use only. Use by updatable result set code.
405
synchronized public PreparedStatement preparePositionedUpdateStatement(String JavaDoc sql, Section querySection) throws SqlException {
406         checkForClosedConnection();
407         // create a net material prepared statement.
408
PreparedStatement preparedStatement = newPositionedUpdatePreparedStatement_(sql, querySection);
409         preparedStatement.flowPrepareDescribeInputOutput();
410         // The positioned update statement is not added to the list of open statements,
411
// because this would cause a java.util.ConcurrentModificationException when
412
// iterating thru the list of open statements to call completeRollback().
413
// An updatable result set is marked closed on a call to completeRollback(),
414
// and would therefore need to close the positioned update statement associated with the result set which would cause
415
// it to be removed from the open statements list. Resulting in concurrent modification
416
// on the open statements list.
417
// Notice that ordinary Statement.closeX() is never called on the positioned update statement,
418
// rather markClosed() is called to avoid trying to remove the statement from the openStatements_ list.
419
return preparedStatement;
420     }
421
422     synchronized public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql) throws SQLException JavaDoc {
423         try
424         {
425             if (agent_.loggingEnabled()) {
426                 agent_.logWriter_.traceEntry(this, "prepareCall", sql);
427             }
428             CallableStatement cs = prepareCallX(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
429             if (agent_.loggingEnabled()) {
430                 agent_.logWriter_.traceExit(this, "prepareCall", cs);
431             }
432             return cs;
433         }
434         catch ( SqlException se )
435         {
436             throw se.getSQLException();
437         }
438     }
439
440     synchronized PreparedStatement prepareDynamicCatalogQuery(String JavaDoc sql) throws SqlException {
441         PreparedStatement ps = newPreparedStatement_(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, holdability(), java.sql.Statement.NO_GENERATED_KEYS, null);
442         ps.isCatalogQuery_ = true;
443         ps.prepare();
444         openStatements_.put(ps, null);
445         return ps;
446     }
447
448     public String JavaDoc nativeSQL(String JavaDoc sql) throws SQLException JavaDoc {
449         try
450         {
451             if (agent_.loggingEnabled()) {
452                 agent_.logWriter_.traceEntry(this, "nativeSQL", sql);
453             }
454             String JavaDoc nativeSql = nativeSQLX(sql);
455             if (agent_.loggingEnabled()) {
456                 agent_.logWriter_.traceExit(this, "nativeSQL", nativeSql);
457             }
458             return nativeSql;
459         }
460         catch ( SqlException se )
461         {
462             throw se.getSQLException();
463         }
464
465     }
466
467     synchronized public String JavaDoc nativeSQLX(String JavaDoc sql) throws SqlException {
468         checkForClosedConnection();
469         if (sql == null) {
470             throw new SqlException(agent_.logWriter_,
471                     new ClientMessageId (SQLState.NULL_SQL_TEXT));
472         }
473
474         // Derby can handle the escape syntax directly so only needs escape
475
// processing for { ? = CALL ....}
476
String JavaDoc trimSql = sql.trim();
477         if (trimSql.startsWith("{")) {
478             if (trimSql.lastIndexOf("}") >= 0) {
479                 return trimSql.substring(1, trimSql.lastIndexOf("}"));
480             }
481         }
482
483         return trimSql;
484     }
485
486     // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
487
// primary usage is distinction between local and global trans. envs.;
488
protected abstract boolean allowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException;
489
490     synchronized public void setAutoCommit(boolean autoCommit) throws SQLException JavaDoc {
491         try
492         {
493             if (agent_.loggingEnabled()) {
494                 agent_.logWriter_.traceEntry(this, "setAutoCommit", autoCommit);
495             }
496             checkForClosedConnection();
497
498             if (! allowLocalCommitRollback_()) {
499                 if (autoCommit) { // can't toggle to autocommit mode when between xars.start() and xars.end()
500
throw new SqlException(agent_.logWriter_,
501                             new ClientMessageId (SQLState.DRDA_NO_AUTOCOMMIT_UNDER_XA));
502                 }
503             } else {
504                 if (autoCommit == autoCommit_) {
505                     return; // don't flow a commit if nothing changed.
506
}
507                 if (inUnitOfWork_) {
508                     flowCommit(); // we are not between xars.start() and xars.end(), can flow commit
509
}
510             }
511             autoCommit_ = autoCommit;
512         }
513         catch ( SqlException se )
514         {
515             throw se.getSQLException();
516         }
517     }
518
519     public boolean getAutoCommit() throws SQLException JavaDoc {
520         try
521         {
522             checkForClosedConnection();
523             if (agent_.loggingEnabled()) {
524                 agent_.logWriter_.traceExit(this, "getAutoCommit", autoCommit_);
525             }
526             if (! allowLocalCommitRollback_()) { // autoCommit is always false between xars.start() and xars.end()
527
return false;
528             }
529             return autoCommit_;
530         }
531         catch ( SqlException se )
532         {
533             throw se.getSQLException();
534         }
535     }
536
537     synchronized public void commit() throws SQLException JavaDoc {
538         try
539         {
540             if (agent_.loggingEnabled()) {
541                 agent_.logWriter_.traceEntry(this, "commit");
542             }
543             checkForClosedConnection();
544
545             // the following XA State check must be in commit instead of commitX since
546
// external application call commit, the SqlException should be thrown
547
// only if an external application calls commit during a Global Transaction,
548
// internal code will call commitX which will ignore the commit request
549
// while in a Global transaction
550
checkForInvalidXAStateOnCommitOrRollback();
551             flowCommit();
552         }
553         catch ( SqlException se )
554         {
555             throw se.getSQLException();
556         }
557     }
558
559     private void checkForInvalidXAStateOnCommitOrRollback() throws SqlException {
560         if (! allowLocalCommitRollback_()) {
561             throw new SqlException(agent_.logWriter_,
562                 new ClientMessageId(SQLState.DRDA_INVALID_XA_STATE_ON_COMMIT_OR_ROLLBACK));
563         }
564     }
565     public void flowCommit() throws SqlException {
566         // Per JDBC specification (see javadoc for Connection.commit()):
567
// "This method should be used only when auto-commit mode has been disabled."
568
// However, some applications do this anyway, it is harmless, so
569
// if they ask to commit, we could go ahead and flow a commit.
570
// But note that rollback() is less harmless, rollback() shouldn't be used in auto-commit mode.
571
// This behavior is subject to further review.
572

573         // if (!this.inUnitOfWork)
574
// return;
575
// We won't try to be "too smart", if the user requests a commit, we'll flow a commit,
576
// regardless of whether or not we're in a unit of work or in auto-commit mode.
577
//
578
if (isXAConnection_) {
579             agent_.beginWriteChainOutsideUOW();
580             writeCommit();
581             agent_.flowOutsideUOW();
582             readCommit(); // This will invoke the commitEvent() callback from the material layer.
583
agent_.endReadChain();
584         } else {
585             agent_.beginWriteChain(null);
586             writeCommit();
587             agent_.flow(null);
588             readCommit(); // This will invoke the commitEvent() callback from the material layer.
589
agent_.endReadChain();
590         }
591
592     }
593
594     // precondition: autoCommit_ is true
595
public boolean flowAutoCommit() throws SqlException {
596         if (willAutoCommitGenerateFlow()) {
597             flowCommit();
598             return true;
599         }
600         return false;
601     }
602
603     public boolean willAutoCommitGenerateFlow() throws org.apache.derby.client.am.SqlException {
604         if (!autoCommit_) {
605             return false;
606         }
607         if (! allowLocalCommitRollback_()) {
608             return false;
609         }
610         return true;
611     }
612
613     // precondition: autoCommit_ is true
614
void writeAutoCommit() throws SqlException {
615         if (willAutoCommitGenerateFlow()) {
616             writeCommit();
617         }
618     }
619
620     public void writeCommit() throws SqlException {
621         if (isXAConnection_) {
622             writeXACommit_ ();
623         } else {
624             writeLocalCommit_();
625         }
626     }
627
628     // precondition: autoCommit_ is true
629
void readAutoCommit() throws SqlException {
630         if (willAutoCommitGenerateFlow()) {
631             readCommit();
632         }
633     }
634
635     public void readCommit() throws SqlException {
636         if (isXAConnection_) {
637             readXACommit_ ();
638         } else {
639             readLocalCommit_();
640         }
641     }
642
643     synchronized public void rollback() throws SQLException JavaDoc {
644         try
645         {
646             if (agent_.loggingEnabled()) {
647                 agent_.logWriter_.traceEntry(this, "rollback");
648             }
649             
650             checkForClosedConnection();
651             checkForInvalidXAStateOnCommitOrRollback();
652
653             flowRollback();
654         }
655         catch ( SqlException se )
656         {
657             throw se.getSQLException();
658         }
659     }
660
661     // Even if we're not in a transaction, all open result sets will be closed.
662
// So we could probably just return if we're not in a transaction
663
// using the following code:
664
// if (!this.inUnitOfWork)
665
// return;
666
// But we'll just play it safe, and blindly flow the rollback.
667
// We won't try to be "too smart", if the user requests a rollback, we'll flow a rollback,
668
// regardless of whether or not we're in a unit of work or in auto-commit mode.
669
//
670
// Per JDBC specification (see javadoc for Connection.rollback()):
671
// "This method should be used only when auto-commit mode has been disabled."
672
// However, rather than trying to be too smart, we'll just flow the rollback anyway
673
// before throwing an exception.
674
// As a side-effect of invoking rollback() in auto-commit mode,
675
// we'll close all open result sets on this connection in the rollbackEvent().
676
//
677
protected void flowRollback() throws SqlException {
678         if (isXAConnection_) {
679             agent_.beginWriteChainOutsideUOW();
680             writeRollback();
681             agent_.flowOutsideUOW();
682             readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
683
agent_.endReadChain();
684         } else {
685             agent_.beginWriteChain(null);
686             writeRollback();
687             agent_.flow(null);
688             readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
689
agent_.endReadChain();
690         }
691     }
692
693     public void writeRollback() throws SqlException {
694         if (isXAConnection_) {
695             writeXARollback_ ();
696         } else {
697             writeLocalRollback_();
698         }
699     }
700
701     public void readRollback() throws SqlException {
702         if (isXAConnection_) {
703             readLocalXARollback_();
704         } else {
705             readLocalRollback_();
706         }
707     }
708
709     synchronized public void close() throws SQLException JavaDoc {
710         if (agent_.loggingEnabled()) {
711             agent_.logWriter_.traceEntry(this, "close");
712         }
713         closeX();
714     }
715
716     void checkForTransactionInProgress() throws SqlException {
717         // The following precondition matches CLI semantics, see SQLDisconnect()
718
if (transactionInProgress() && !allowCloseInUOW_()) {
719             throw new SqlException(agent_.logWriter_,
720                     new ClientMessageId (SQLState.CANNOT_CLOSE_ACTIVE_CONNECTION));
721         }
722     }
723     
724     public boolean transactionInProgress() {
725         return !autoCommit_ && inUnitOfWork_;
726     }
727
728     // This is a no-op if the connection is already closed.
729
synchronized public void closeX() throws SQLException JavaDoc {
730         if (!open_) {
731             return;
732         }
733         closeResourcesX();
734     }
735
736     // Close physical socket or attachment even if connection is marked close.
737
// Used by ClientPooledConnection.close().
738
synchronized public void closeResources() throws SQLException JavaDoc {
739         if (open_ || (!open_ && availableForReuse_)) {
740             availableForReuse_ = false;
741             closeResourcesX();
742         }
743     }
744
745     private void closeResourcesX() throws SQLException JavaDoc {
746         try
747         {
748             checkForTransactionInProgress();
749         }
750         catch ( SqlException e )
751         {
752             throw e.getSQLException();
753         }
754         
755         resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
756
SQLException JavaDoc accumulatedExceptions = null;
757         if (setTransactionIsolationStmt != null) {
758             try {
759                 setTransactionIsolationStmt.close();
760             } catch (SQLException JavaDoc se) {
761                 accumulatedExceptions = se;
762             }
763         }
764         setTransactionIsolationStmt = null;
765         if (getTransactionIsolationStmt != null) {
766             try {
767                 getTransactionIsolationStmt.close();
768             } catch (SQLException JavaDoc se) {
769                 accumulatedExceptions = Utils.accumulateSQLException(
770                         se, accumulatedExceptions);
771             }
772         }
773         getTransactionIsolationStmt = null;
774         try {
775             flowClose();
776         } catch (SqlException e) {
777             accumulatedExceptions =
778                     Utils.accumulateSQLException(
779                         e.getSQLException(), accumulatedExceptions);
780         }
781
782         markClosed();
783         try {
784             agent_.close();
785         } catch (SqlException e) {
786             throw Utils.accumulateSQLException(e.getSQLException(),
787                 accumulatedExceptions);
788         }
789     }
790
791     protected abstract boolean isGlobalPending_();
792
793     // Just like closeX except the socket is not pulled.
794
// Physical resources are not closed.
795
synchronized public void closeForReuse() throws SqlException {
796         if (!open_) {
797             return;
798         }
799         resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
800
SqlException accumulatedExceptions = null;
801         try {
802             flowClose();
803         } catch (SqlException e) {
804             accumulatedExceptions = e;
805         }
806         if (open_) {
807             markClosedForReuse();
808         }
809         if (accumulatedExceptions != null) {
810             throw accumulatedExceptions;
811         }
812     }
813
814     private void flowClose() throws SqlException {
815         agent_.beginWriteChainOutsideUOW();
816         if (doCloseStatementsOnClose_()) {
817             writeCloseStatements();
818         }
819         if (autoCommit_) {
820             writeAutoCommit();
821         }
822         agent_.flowOutsideUOW();
823         if (doCloseStatementsOnClose_()) {
824             readCloseStatements();
825         }
826         if (autoCommit_) {
827             readAutoCommit();
828         }
829         agent_.endReadChain();
830     }
831
832     protected abstract void markClosed_();
833
834     public void markClosed() // called by LogicalConnection.close()
835
{
836         open_ = false;
837         inUnitOfWork_ = false;
838         markStatementsClosed();
839         CommitAndRollbackListeners_.clear();
840         markClosed_();
841     }
842
843
844     private void markClosedForReuse() {
845         availableForReuse_ = true;
846         markClosed();
847     }
848
849     private void markStatementsClosed() {
850         java.util.Set JavaDoc keySet = openStatements_.keySet();
851         for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
852             Statement stmt = (Statement) i.next();
853             stmt.markClosed();
854             i.remove();
855         }
856     }
857
858     private void writeCloseStatements() throws SqlException {
859         java.util.Set JavaDoc keySet = openStatements_.keySet();
860         for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
861             ((Statement) i.next()).writeClose(false); // false means don't permit auto-commits
862
}
863     }
864
865     private void readCloseStatements() throws SqlException {
866         java.util.Set JavaDoc keySet = openStatements_.keySet();
867         for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
868             ((Statement) i.next()).readClose(false); // false means don't permit auto-commits
869
}
870     }
871
872    /**
873     * Return true if the physical connection is still open.
874     * Might be logically closed but available for reuse.
875     * @return true if physical connection still open
876     */

877     public boolean isPhysicalConnClosed() {
878     return !open_ && !availableForReuse_;
879    }
880
881    
882     public boolean isClosed() {
883         if (agent_.loggingEnabled()) {
884             agent_.logWriter_.traceExit(this, "isClosed", !open_);
885         }
886         return !open_;
887     }
888
889    
890     public boolean isClosedX() {
891         return !open_;
892     }
893
894     private static String JavaDoc DERBY_TRANSACTION_REPEATABLE_READ = "RS";
895     private static String JavaDoc DERBY_TRANSACTION_SERIALIZABLE = "RR";
896     private static String JavaDoc DERBY_TRANSACTION_READ_COMMITTED = "CS";
897     private static String JavaDoc DERBY_TRANSACTION_READ_UNCOMMITTED = "UR";
898
899     synchronized public void setTransactionIsolation(int level) throws SQLException JavaDoc {
900         try
901         {
902             if (agent_.loggingEnabled()) {
903                 agent_.logWriter_.traceEntry(this, "setTransactionIsolation", level);
904             }
905             // Per jdbc spec (see java.sql.Connection.close() javadoc).
906
checkForClosedConnection();
907
908             // Javadoc for this method:
909
// If this method is called during a transaction, the result is implementation-defined.
910
//
911
//
912
// REPEATABLE_READ = JDBC: TRANSACTION_SERIALIZABLE, DERBY: RR, PROTOCOL: repeatable read
913
// READ_STABILITY = JDBC: TRANSACTION_REPEATABLE_READ, DERBY: RS, PROTOCOL: All
914
// CURSOR_STABILITY = JDBC: TRANSACTION_READ_COMMITTED, DERBY: CS, PROTOCOL: Cursor stability
915
// UNCOMMITTED_READ = JDBC: TRANSACTION_READ_UNCOMMITTED, DERBY: UR , PROTOCOL: Change
916
// NO_COMMIT = JDBC: TRANSACTION_NONE, DERBY: NC, PROTOCOL: No commit
917
//
918
String JavaDoc levelString = null;
919             switch (level) {
920             case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
921                 levelString = DERBY_TRANSACTION_REPEATABLE_READ;
922                 break;
923             case java.sql.Connection.TRANSACTION_READ_COMMITTED:
924                 levelString = DERBY_TRANSACTION_READ_COMMITTED;
925                 break;
926             case java.sql.Connection.TRANSACTION_SERIALIZABLE:
927                 levelString = DERBY_TRANSACTION_SERIALIZABLE;
928                 break;
929             case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
930                 levelString = DERBY_TRANSACTION_READ_UNCOMMITTED;
931                 break;
932                 // Per javadoc:
933
// Note that Connection.TRANSACTION_NONE cannot be used because it specifies that transactions are not supported.
934
case java.sql.Connection.TRANSACTION_NONE:
935             default:
936                 throw new SqlException(agent_.logWriter_,
937                     new ClientMessageId (SQLState.UNIMPLEMENTED_ISOLATION_LEVEL),
938                     new Integer JavaDoc(level));
939             }
940             if (setTransactionIsolationStmt == null ||
941                     !(setTransactionIsolationStmt.openOnClient_ &&
942                             setTransactionIsolationStmt.openOnServer_)) {
943                 setTransactionIsolationStmt =
944                         createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
945                                 java.sql.ResultSet.CONCUR_READ_ONLY,
946                                 holdability());
947             }
948
949             setTransactionIsolationStmt.executeUpdate("SET CURRENT ISOLATION = " + levelString);
950
951             // The server has now implicitely committed the
952
// transaction so we have to clean up locally.
953
completeLocalCommit();
954
955             isolation_ = level;
956         }
957         catch ( SqlException se )
958         {
959             throw se.getSQLException();
960         }
961     }
962
963     public int getTransactionIsolation() throws SQLException JavaDoc {
964         
965         // Store the current auto-commit value and use it to restore
966
// at the end of this method.
967
boolean currentAutoCommit = autoCommit_;
968         java.sql.ResultSet JavaDoc rs = null;
969         
970         try
971         {
972             checkForClosedConnection();
973             if (agent_.loggingEnabled()) {
974                 agent_.logWriter_.traceExit(this, "getTransactionIsolation", isolation_);
975             }
976             
977             // Set auto-commit to false when executing the statement as we do not want to
978
// cause an auto-commit from getTransactionIsolation() method.
979
autoCommit_ = false;
980             
981             // DERBY-1148 - Client reports wrong isolation level. We need to get the isolation
982
// level from the server. 'isolation_' maintained in the client's connection object
983
// can be out of sync with the real isolation when in an XA transaction. This can
984
// also happen when isolation is set using SQL instead of JDBC. So we try to get the
985
// value from the server by calling the "current isolation" function. If we fail to
986
// get the value, return the value stored in the client's connection object.
987
if (getTransactionIsolationStmt == null ||
988                     !(getTransactionIsolationStmt.openOnClient_ &&
989                             getTransactionIsolationStmt.openOnServer_)) {
990                 getTransactionIsolationStmt =
991                         createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
992                                 java.sql.ResultSet.CONCUR_READ_ONLY,
993                                 holdability());
994             }
995             
996             boolean savedInUnitOfWork = inUnitOfWork_;
997             rs = getTransactionIsolationStmt.executeQuery("values current isolation");
998             rs.next();
999             String JavaDoc isolationStr = rs.getString(1);
1000            isolation_ = translateIsolation(isolationStr);
1001            rs.close();
1002            // So... of we did not have an active transaction before
1003
// the query, we pretend to still not have an open
1004
// transaction. The result set is closed, so this should
1005
// not be problematic. DERBY-2084
1006
inUnitOfWork_ = savedInUnitOfWork;
1007        }
1008        catch ( SqlException se )
1009        {
1010            throw se.getSQLException();
1011        }
1012        finally {
1013            // Restore auto-commit value
1014
autoCommit_ = currentAutoCommit;
1015            if(rs != null)
1016                rs.close();
1017        }
1018        
1019        return isolation_;
1020    }
1021  
1022    /**
1023     * Translates the isolation level from a SQL string to the JDBC int value
1024     *
1025     * @param isolationStr SQL isolation string
1026     * @return isolation level as a JDBC integer value
1027     */

1028    private int translateIsolation(String JavaDoc isolationStr) {
1029        if(isolationStr.compareTo(DERBY_TRANSACTION_REPEATABLE_READ) == 0)
1030            return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
1031        else if (isolationStr.compareTo(DERBY_TRANSACTION_SERIALIZABLE) == 0)
1032            return java.sql.Connection.TRANSACTION_SERIALIZABLE;
1033        else if (isolationStr.compareTo(DERBY_TRANSACTION_READ_COMMITTED) == 0)
1034            return java.sql.Connection.TRANSACTION_READ_COMMITTED;
1035        else if (isolationStr.compareTo(DERBY_TRANSACTION_READ_UNCOMMITTED) == 0)
1036            return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
1037        else
1038            return java.sql.Connection.TRANSACTION_NONE;
1039    }
1040
1041    public java.sql.SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc {
1042        if (agent_.loggingEnabled()) {
1043            agent_.logWriter_.traceExit(this, "getWarnings", warnings_);
1044        }
1045        try {
1046            checkForClosedConnection();
1047        } catch (SqlException se) {
1048            throw se.getSQLException();
1049        }
1050        return warnings_ == null ? null : warnings_.getSQLWarning();
1051    }
1052
1053    synchronized public void clearWarnings() throws SQLException JavaDoc {
1054        try
1055        {
1056            if (agent_.loggingEnabled()) {
1057                agent_.logWriter_.traceEntry(this, "clearWarnings");
1058            }
1059            checkForClosedConnection();
1060            clearWarningsX();
1061        }
1062        catch ( SqlException se )
1063        {
1064            throw se.getSQLException();
1065        }
1066    }
1067
1068    // An untraced version of clearWarnings()
1069
public void clearWarningsX() throws SqlException {
1070        warnings_ = null;
1071        accumulated440ForMessageProcFailure_ = false;
1072        accumulated444ForMessageProcFailure_ = false;
1073        accumulatedSetReadOnlyWarning_ = false;
1074    }
1075
1076    //======================================================================
1077
// Advanced features:
1078

1079    public java.sql.DatabaseMetaData JavaDoc getMetaData() throws SQLException JavaDoc {
1080        try
1081        {
1082            checkForClosedConnection();
1083            if (agent_.loggingEnabled()) {
1084                agent_.logWriter_.traceExit(this, "getMetaData", databaseMetaData_);
1085            }
1086            return databaseMetaData_;
1087        }
1088        catch ( SqlException se )
1089        {
1090            throw se.getSQLException();
1091        }
1092    }
1093
1094    synchronized public void setReadOnly(boolean readOnly) throws SQLException JavaDoc {
1095        try
1096        {
1097            // This is a hint to the driver only, so this request is silently ignored.
1098
// PROTOCOL can only flow a set-read-only before the connection is established.
1099
if (agent_.loggingEnabled()) {
1100                agent_.logWriter_.traceEntry(this, "setReadOnly", readOnly);
1101            }
1102            checkForClosedConnection();
1103        }
1104        catch ( SqlException se )
1105        {
1106            throw se.getSQLException();
1107        }
1108    }
1109
1110    public boolean isReadOnly() throws SQLException JavaDoc {
1111        try
1112        {
1113            checkForClosedConnection();
1114            if (agent_.loggingEnabled()) {
1115                agent_.logWriter_.traceExit(this, "isReadOnly", jdbcReadOnly_);
1116            }
1117            return false;
1118        }
1119        catch ( SqlException se )
1120        {
1121            throw se.getSQLException();
1122        }
1123    }
1124
1125    synchronized public void setCatalog(String JavaDoc catalog) throws SQLException JavaDoc {
1126        try
1127        {
1128            if (agent_.loggingEnabled()) {
1129                agent_.logWriter_.traceEntry(this, "setCatalog", catalog);
1130            }
1131            checkForClosedConnection();
1132            // Per jdbc spec: if the driver does not support catalogs, it will silently ignore this request.
1133
}
1134        catch ( SqlException se )
1135        {
1136            throw se.getSQLException();
1137        }
1138    }
1139
1140    public String JavaDoc getCatalog() throws SQLException JavaDoc {
1141        try
1142        {
1143            checkForClosedConnection();
1144            if (agent_.loggingEnabled()) {
1145                agent_.logWriter_.traceExit(this, "getCatalog", (String JavaDoc) null);
1146            }
1147            return null;
1148        }
1149        catch ( SqlException se )
1150        {
1151            throw se.getSQLException();
1152        }
1153    }
1154
1155    //--------------------------JDBC 2.0-----------------------------
1156

1157    synchronized public java.sql.Statement JavaDoc createStatement(int resultSetType,
1158                                                           int resultSetConcurrency) throws SQLException JavaDoc {
1159        try
1160        {
1161            if (agent_.loggingEnabled()) {
1162                agent_.logWriter_.traceEntry(this, "createStatement", resultSetType, resultSetConcurrency);
1163            }
1164            Statement s = createStatementX(resultSetType, resultSetConcurrency, holdability());
1165            if (agent_.loggingEnabled()) {
1166                agent_.logWriter_.traceExit(this, "createStatement", s);
1167            }
1168            return s;
1169        }
1170        catch ( SqlException se )
1171        {
1172            throw se.getSQLException();
1173        }
1174    }
1175
1176    synchronized public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
1177                                                                    int resultSetType,
1178                                                                    int resultSetConcurrency) throws SQLException JavaDoc {
1179        try
1180        {
1181            if (agent_.loggingEnabled()) {
1182                agent_.logWriter_.traceEntry(this, "prepareStatement", sql, resultSetType, resultSetConcurrency);
1183            }
1184            PreparedStatement ps = prepareStatementX(sql,
1185                    resultSetType,
1186                    resultSetConcurrency,
1187                    holdability(),
1188                    java.sql.Statement.NO_GENERATED_KEYS,
1189                    null);
1190            if (agent_.loggingEnabled()) {
1191                agent_.logWriter_.traceExit(this, "prepareStatement", ps);
1192            }
1193            return ps;
1194        }
1195        catch ( SqlException se )
1196        {
1197            throw se.getSQLException();
1198        }
1199    }
1200
1201    synchronized public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql,
1202                                                               int resultSetType,
1203                                                               int resultSetConcurrency) throws SQLException JavaDoc {
1204        try
1205        {
1206            if (agent_.loggingEnabled()) {
1207                agent_.logWriter_.traceEntry(this, "prepareCall", sql, resultSetType, resultSetConcurrency);
1208            }
1209            CallableStatement cs = prepareCallX(sql, resultSetType, resultSetConcurrency, holdability());
1210            if (agent_.loggingEnabled()) {
1211                agent_.logWriter_.traceExit(this, "prepareCall", cs);
1212            }
1213            return cs;
1214        }
1215        catch ( SqlException se )
1216        {
1217            throw se.getSQLException();
1218        }
1219    }
1220
1221    synchronized public CallableStatement prepareMessageProc(String JavaDoc sql) throws SqlException {
1222        checkForClosedConnection();
1223
1224        CallableStatement cs = prepareCallX(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
1225        return cs;
1226    }
1227
1228    // Per jdbc spec, when a result set type is unsupported, we downgrade and
1229
// issue a warning rather than to throw an exception.
1230
private int downgradeResultSetType(int resultSetType) {
1231        if (resultSetType == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE) {
1232            accumulateWarning(new SqlWarning(agent_.logWriter_,
1233                new ClientMessageId(SQLState.SCROLL_SENSITIVE_NOT_SUPPORTED)));
1234            return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
1235        }
1236        return resultSetType;
1237    }
1238
1239    public java.util.Map JavaDoc getTypeMap() throws SQLException JavaDoc {
1240        try
1241        {
1242            if (agent_.loggingEnabled()) {
1243                agent_.logWriter_.traceEntry(this, "getTypeMap");
1244            }
1245            checkForClosedConnection();
1246            java.util.Map JavaDoc map = new java.util.HashMap JavaDoc();
1247            if (agent_.loggingEnabled()) {
1248                agent_.logWriter_.traceExit(this, "getTypeMap", map);
1249            }
1250            return map;
1251        }
1252        catch ( SqlException se )
1253        {
1254            throw se.getSQLException();
1255        }
1256    }
1257
1258    synchronized public void setTypeMap(java.util.Map JavaDoc map) throws SQLException JavaDoc {
1259        try
1260        {
1261            if (agent_.loggingEnabled()) {
1262                agent_.logWriter_.traceEntry(this, "setTypeMap", map);
1263            }
1264            checkForClosedConnection();
1265            throw new SqlException(agent_.logWriter_,
1266                    new ClientMessageId (SQLState.NOT_IMPLEMENTED),
1267                    "setTypeMap");
1268        }
1269        catch ( SqlException se )
1270        {
1271            throw se.getSQLException();
1272        }
1273    }
1274
1275    //--------------------------JDBC 3.0-----------------------------
1276

1277    synchronized public void setHoldability(int holdability) throws SQLException JavaDoc {
1278        try
1279        {
1280            if (agent_.loggingEnabled()) {
1281                agent_.logWriter_.traceEntry(this, "setHoldability", holdability);
1282            }
1283            checkForClosedConnection();
1284            // In an XA global transaction do not allow the
1285
// holdability to be set to hold cursors across
1286
// commits, as the engine does not support it.
1287
if (this.isXAConnection_ && this.xaState_ == XA_T1_ASSOCIATED)
1288            {
1289                if (holdability == JDBC30Translation.HOLD_CURSORS_OVER_COMMIT)
1290                    throw new SqlException(agent_.logWriter_,
1291                            new ClientMessageId(SQLState.CANNOT_HOLD_CURSOR_XA));
1292            }
1293            this.holdability = holdability;
1294            
1295       }
1296        catch ( SqlException se )
1297        {
1298            throw se.getSQLException();
1299        }
1300    }
1301
1302    public int getHoldability() throws SQLException JavaDoc {
1303        try
1304        {
1305            checkForClosedConnection();
1306            if (agent_.loggingEnabled()) {
1307                agent_.logWriter_.traceExit(this, "getHoldability", holdability());
1308            }
1309            return holdability();
1310        }
1311        catch ( SqlException se )
1312        {
1313            throw se.getSQLException();
1314        }
1315    }
1316
1317    public int dncGeneratedSavepointId_;
1318    // generated name used internally for unnamed savepoints
1319
public static final String JavaDoc dncGeneratedSavepointNamePrefix__ = "DNC_GENENERATED_NAME_";
1320
1321    synchronized public java.sql.Savepoint JavaDoc setSavepoint() throws SQLException JavaDoc {
1322        try
1323        {
1324            if (agent_.loggingEnabled()) {
1325                agent_.logWriter_.traceEntry(this, "setSavepoint");
1326            }
1327            checkForClosedConnection();
1328            if (autoCommit_) // Throw exception if auto-commit is on
1329
{
1330                throw new SqlException(agent_.logWriter_,
1331                        new ClientMessageId (SQLState.NO_SAVEPOINT_WHEN_AUTO));
1332            }
1333            // create an un-named savepoint.
1334
if ((++dncGeneratedSavepointId_) < 0) {
1335                dncGeneratedSavepointId_ = 1; // restart from 1 when overflow.
1336
}
1337            Object JavaDoc s = setSavepointX(new Savepoint(agent_, dncGeneratedSavepointId_));
1338            return (java.sql.Savepoint JavaDoc) s;
1339        }
1340        catch ( SqlException se )
1341        {
1342            throw se.getSQLException();
1343        }
1344    }
1345
1346    synchronized public java.sql.Savepoint JavaDoc setSavepoint(String JavaDoc name) throws SQLException JavaDoc {
1347        try
1348        {
1349            if (agent_.loggingEnabled()) {
1350                agent_.logWriter_.traceEntry(this, "setSavepoint", name);
1351            }
1352            checkForClosedConnection();
1353            if (name == null) // Throw exception if savepoint name is null
1354
{
1355                throw new SqlException(agent_.logWriter_,
1356                        new ClientMessageId (SQLState.NULL_NAME_FOR_SAVEPOINT));
1357            } else if (autoCommit_) // Throw exception if auto-commit is on
1358
{
1359                throw new SqlException(agent_.logWriter_,
1360                        new ClientMessageId (SQLState.NO_SAVEPOINT_WHEN_AUTO));
1361            }
1362            // create a named savepoint.
1363
Object JavaDoc s = setSavepointX(new Savepoint(agent_, name));
1364            return (java.sql.Savepoint JavaDoc) s;
1365        }
1366        catch ( SqlException se )
1367        {
1368            throw se.getSQLException();
1369        }
1370    }
1371
1372    private Savepoint setSavepointX(Savepoint savepoint) throws SQLException JavaDoc {
1373        // Construct and flow a savepoint statement to server.
1374
Statement stmt = null;
1375        try {
1376            stmt = (Statement) createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
1377                    java.sql.ResultSet.CONCUR_READ_ONLY,
1378                    holdability());
1379            String JavaDoc savepointName;
1380            try {
1381                savepointName = savepoint.getSavepointName();
1382            } catch (SQLException JavaDoc e) {
1383                // generate the name for an un-named savepoint.
1384
savepointName = dncGeneratedSavepointNamePrefix__ +
1385                        savepoint.getSavepointId();
1386            }
1387            String JavaDoc sql = "SAVEPOINT \"" + savepointName + "\" ON ROLLBACK RETAIN CURSORS";
1388            stmt.executeX(sql);
1389        } catch ( SqlException se )
1390        {
1391            throw se.getSQLException();
1392        } finally {
1393            if (stmt != null) {
1394                try {
1395                    stmt.closeX();
1396                } catch (SqlException doNothing) {
1397                }
1398            }
1399        }
1400
1401        return savepoint;
1402    }
1403
1404    synchronized public void rollback(java.sql.Savepoint JavaDoc savepoint) throws SQLException JavaDoc {
1405        try
1406        {
1407            int saveXaState = xaState_;
1408            if (agent_.loggingEnabled()) {
1409                agent_.logWriter_.traceEntry(this, "rollback", savepoint);
1410            }
1411            checkForClosedConnection();
1412            if (savepoint == null) // Throw exception if savepoint is null
1413
{
1414                throw new SqlException(agent_.logWriter_,
1415                        new ClientMessageId (SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL));
1416            } else if (autoCommit_) // Throw exception if auto-commit is on
1417
{
1418                throw new SqlException(agent_.logWriter_,
1419                        new ClientMessageId (SQLState.NO_SAVEPOINT_ROLLBACK_OR_RELEASE_WHEN_AUTO));
1420            }
1421            // Only allow to rollback to a savepoint from the connection that create the savepoint.
1422
try {
1423                if (this != ((Savepoint) savepoint).agent_.connection_) {
1424                    throw new SqlException(agent_.logWriter_,
1425                            new ClientMessageId (SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1426                }
1427            } catch (java.lang.ClassCastException JavaDoc e) { // savepoint is not an instance of am.Savepoint
1428
throw new SqlException(agent_.logWriter_,
1429                        new ClientMessageId (SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1430            }
1431
1432            // Construct and flow a savepoint rollback statement to server.
1433
Statement stmt = null;
1434            try {
1435                stmt = createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
1436                        java.sql.ResultSet.CONCUR_READ_ONLY,
1437                        holdability());
1438                String JavaDoc savepointName;
1439                try {
1440                    savepointName = ((Savepoint) savepoint).getSavepointName();
1441                } catch (SQLException JavaDoc e) {
1442                    // generate the name for an un-named savepoint.
1443
savepointName = dncGeneratedSavepointNamePrefix__ +
1444                            ((Savepoint) savepoint).getSavepointId();
1445                }
1446                String JavaDoc sql = "ROLLBACK TO SAVEPOINT \"" + savepointName + "\"";
1447                stmt.executeX(sql);
1448            } finally {
1449                if (stmt != null) {
1450                    try {
1451                        stmt.closeX();
1452                    } catch (SqlException doNothing) {
1453                    }
1454                }
1455                xaState_ = saveXaState;
1456            }
1457        }
1458        catch ( SqlException se )
1459        {
1460            throw se.getSQLException();
1461        }
1462    }
1463
1464    synchronized public void releaseSavepoint(java.sql.Savepoint JavaDoc savepoint) throws SQLException JavaDoc {
1465        try
1466        {
1467            int saveXaState = xaState_;
1468            if (agent_.loggingEnabled()) {
1469                agent_.logWriter_.traceEntry(this, "releaseSavepoint", savepoint);
1470            }
1471            checkForClosedConnection();
1472            if (savepoint == null) // Throw exception if savepoint is null
1473
{
1474                throw new SqlException(agent_.logWriter_,
1475                        new ClientMessageId (SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL));
1476            } else if (autoCommit_) // Throw exception if auto-commit is on
1477
{
1478                throw new SqlException(agent_.logWriter_,
1479                        new ClientMessageId (SQLState.NO_SAVEPOINT_ROLLBACK_OR_RELEASE_WHEN_AUTO));
1480            }
1481            // Only allow to release a savepoint from the connection that create the savepoint.
1482
try {
1483                if (this != ((Savepoint) savepoint).agent_.connection_) {
1484                    throw new SqlException(agent_.logWriter_, new ClientMessageId
1485                            (SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1486                }
1487            } catch (java.lang.ClassCastException JavaDoc e) { // savepoint is not an instance of am.Savepoint
1488
throw new SqlException(agent_.logWriter_, new ClientMessageId
1489                            (SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1490
1491            }
1492
1493            // Construct and flow a savepoint release statement to server.
1494
Statement stmt = null;
1495            try {
1496                stmt = (Statement) createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
1497                        java.sql.ResultSet.CONCUR_READ_ONLY,
1498                        holdability());
1499                String JavaDoc savepointName;
1500                try {
1501                    savepointName = ((Savepoint) savepoint).getSavepointName();
1502                } catch (SQLException JavaDoc e) {
1503                    // generate the name for an un-named savepoint.
1504
savepointName = dncGeneratedSavepointNamePrefix__ +
1505                            ((Savepoint) savepoint).getSavepointId();
1506                }
1507                String JavaDoc sql = "RELEASE SAVEPOINT \"" + savepointName + "\"";
1508                stmt.executeX(sql);
1509            } finally {
1510                if (stmt != null) {
1511                    try {
1512                        stmt.closeX();
1513                    } catch (SqlException doNothing) {
1514                    }
1515                }
1516                xaState_ = saveXaState;
1517            }
1518        }
1519        catch ( SqlException se )
1520        {
1521            throw se.getSQLException();
1522        }
1523    }
1524
1525    synchronized public java.sql.Statement JavaDoc createStatement(int resultSetType,
1526                                                           int resultSetConcurrency,
1527                                                           int resultSetHoldability) throws SQLException JavaDoc {
1528        try
1529        {
1530            if (agent_.loggingEnabled()) {
1531                agent_.logWriter_.traceEntry(this, "createStatement", resultSetType, resultSetConcurrency, resultSetHoldability);
1532            }
1533            Statement s = createStatementX(resultSetType, resultSetConcurrency, resultSetHoldability);
1534            if (agent_.loggingEnabled()) {
1535                agent_.logWriter_.traceExit(this, "createStatement", s);
1536            }
1537            return s;
1538        }
1539        catch ( SqlException se )
1540        {
1541            throw se.getSQLException();
1542        }
1543    }
1544
1545    private Statement createStatementX(int resultSetType,
1546                                       int resultSetConcurrency,
1547                                       int resultSetHoldability) throws SqlException {
1548        checkForClosedConnection();
1549        resultSetType = downgradeResultSetType(resultSetType);
1550        // In an XA global transaction do not allow the
1551
// holdability to be set to hold cursors across
1552
// commits, as the engine does not support it.
1553
// Downgrade the holdability to CLOSE_CURSORS_AT_COMMIT
1554
// and attach a warning. This is specified in
1555
// JDBC 4.0 (proposed final draft) section 16.1.3.1
1556
// Similar code is not needed for PreparedStatement
1557
// as the holdability gets pushed all the way to the
1558
// engine and handled there.
1559
if (this.isXAConnection_ && this.xaState_ == XA_T1_ASSOCIATED)
1560        {
1561            if (resultSetHoldability == JDBC30Translation.HOLD_CURSORS_OVER_COMMIT) {
1562                resultSetHoldability = JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
1563                accumulateWarning(new SqlWarning(agent_.logWriter_,
1564                        new ClientMessageId(SQLState.HOLDABLE_RESULT_SET_NOT_AVAILABLE)));
1565            }
1566        }
1567        Statement s = newStatement_(resultSetType, resultSetConcurrency, resultSetHoldability);
1568        s.cursorAttributesToSendOnPrepare_ = s.cacheCursorAttributesToSendOnPrepare();
1569        openStatements_.put(s, null);
1570        return s;
1571    }
1572
1573    // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
1574
// right thing to do here... because if property on the dataSource changes, we may have
1575
// to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
1576
protected void resetStatement(Statement s) throws SqlException {
1577        String JavaDoc cursorAttributesToSendOnPrepare = s.cursorAttributesToSendOnPrepare_;
1578        resetStatement_(s, s.resultSetType_, s.resultSetConcurrency_, s.resultSetHoldability_);
1579        s.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1580    }
1581
1582    synchronized public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
1583                                                                    int resultSetType,
1584                                                                    int resultSetConcurrency,
1585                                                                    int resultSetHoldability) throws SQLException JavaDoc {
1586        try
1587        {
1588            if (agent_.loggingEnabled()) {
1589                agent_.logWriter_.traceEntry(this, "prepareStatement", sql, resultSetType, resultSetConcurrency, resultSetHoldability);
1590            }
1591            PreparedStatement ps = prepareStatementX(sql,
1592                    resultSetType,
1593                    resultSetConcurrency,
1594                    resultSetHoldability,
1595                    java.sql.Statement.NO_GENERATED_KEYS,
1596                    null);
1597            if (agent_.loggingEnabled()) {
1598                agent_.logWriter_.traceExit(this, "prepareStatement", ps);
1599            }
1600            return ps;
1601        }
1602        catch ( SqlException se )
1603        {
1604            throw se.getSQLException();
1605        }
1606    }
1607
1608    // used by DBMD
1609
PreparedStatement prepareStatementX(String JavaDoc sql,
1610                                        int resultSetType,
1611                                        int resultSetConcurrency,
1612                                        int resultSetHoldability,
1613                                        int autoGeneratedKeys,
1614                                        String JavaDoc[] columnNames) throws SqlException {
1615        checkForClosedConnection();
1616        checkAutoGeneratedKeysParameters(autoGeneratedKeys, columnNames);
1617        resultSetType = downgradeResultSetType(resultSetType);
1618        PreparedStatement ps = newPreparedStatement_(sql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnNames);
1619        ps.cursorAttributesToSendOnPrepare_ = ps.cacheCursorAttributesToSendOnPrepare();
1620        ps.prepare();
1621        openStatements_.put(ps,null);
1622        return ps;
1623    }
1624
1625    // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
1626
// right thing to do here... because if property on the dataSource changes, we may have
1627
// to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
1628
protected void resetPrepareStatement(PreparedStatement ps) throws SqlException {
1629        String JavaDoc cursorAttributesToSendOnPrepare = ps.cursorAttributesToSendOnPrepare_;
1630        resetPreparedStatement_(ps, ps.sql_, ps.resultSetType_, ps.resultSetConcurrency_, ps.resultSetHoldability_, ps.autoGeneratedKeys_, ps.generatedKeysColumnNames_);
1631        ps.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1632        ps.prepare();
1633    }
1634
1635    synchronized public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql,
1636                                                               int resultSetType,
1637                                                               int resultSetConcurrency,
1638                                                               int resultSetHoldability) throws SQLException JavaDoc {
1639        try
1640        {
1641            if (agent_.loggingEnabled()) {
1642                agent_.logWriter_.traceEntry(this, "prepareCall", sql, resultSetType, resultSetConcurrency, resultSetHoldability);
1643            }
1644            CallableStatement cs = prepareCallX(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
1645            if (agent_.loggingEnabled()) {
1646                agent_.logWriter_.traceExit(this, "prepareCall", cs);
1647            }
1648            return cs;
1649        }
1650        catch ( SqlException se )
1651        {
1652            throw se.getSQLException();
1653        }
1654    }
1655
1656    private CallableStatement prepareCallX(String JavaDoc sql,
1657                                           int resultSetType,
1658                                           int resultSetConcurrency,
1659                                           int resultSetHoldability) throws SqlException {
1660        checkForClosedConnection();
1661        resultSetType = downgradeResultSetType(resultSetType);
1662        CallableStatement cs = newCallableStatement_(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
1663        cs.cursorAttributesToSendOnPrepare_ = cs.cacheCursorAttributesToSendOnPrepare();
1664        cs.prepare();
1665        openStatements_.put(cs,null);
1666        return cs;
1667    }
1668
1669    protected void resetPrepareCall(CallableStatement cs) throws SqlException {
1670        String JavaDoc cursorAttributesToSendOnPrepare = cs.cursorAttributesToSendOnPrepare_;
1671        resetCallableStatement_(cs, cs.sql_, cs.resultSetType_, cs.resultSetConcurrency_, cs.resultSetHoldability_);
1672        cs.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1673        cs.prepare();
1674    }
1675
1676    public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int autoGeneratedKeys) throws SQLException JavaDoc {
1677        try
1678        {
1679            if (agent_.loggingEnabled()) {
1680                agent_.logWriter_.traceEntry(this, "prepareStatement", sql, autoGeneratedKeys);
1681            }
1682            PreparedStatement ps = prepareStatementX(sql,
1683                    java.sql.ResultSet.TYPE_FORWARD_ONLY,
1684                    java.sql.ResultSet.CONCUR_READ_ONLY,
1685                    holdability(),
1686                    autoGeneratedKeys,
1687                    null);
1688            if (agent_.loggingEnabled()) {
1689                agent_.logWriter_.traceExit(this, "prepareStatement", ps);
1690            }
1691            return ps;
1692        }
1693        catch ( SqlException se )
1694        {
1695            throw se.getSQLException();
1696        }
1697    }
1698
1699    public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int columnIndexes[]) throws SQLException JavaDoc {
1700        try
1701        {
1702            if (agent_.loggingEnabled()) {
1703                agent_.logWriter_.traceEntry(this, "prepareStatement", sql, columnIndexes);
1704            }
1705            checkForClosedConnection();
1706            throw new SqlException(agent_.logWriter_,
1707                new ClientMessageId (SQLState.NOT_IMPLEMENTED),
1708                "prepareStatement(String, int[])");
1709        }
1710        catch ( SqlException se )
1711        {
1712            throw se.getSQLException();
1713        }
1714    }
1715
1716    public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, String JavaDoc columnNames[]) throws SQLException JavaDoc {
1717        try
1718        {
1719            if (agent_.loggingEnabled()) {
1720                agent_.logWriter_.traceEntry(this, "prepareStatement", sql, columnNames);
1721            }
1722            PreparedStatement ps = prepareStatementX(sql,
1723                    java.sql.ResultSet.TYPE_FORWARD_ONLY,
1724                    java.sql.ResultSet.CONCUR_READ_ONLY,
1725                    holdability(),
1726                    java.sql.Statement.RETURN_GENERATED_KEYS,
1727                    columnNames);
1728            if (agent_.loggingEnabled()) {
1729                agent_.logWriter_.traceExit(this, "prepareStatement", ps);
1730            }
1731            return ps;
1732        }
1733        catch ( SqlException se )
1734        {
1735            throw se.getSQLException();
1736        }
1737    }
1738
1739
1740    // ---------------------------------------------------------------------------
1741

1742    protected abstract boolean allowCloseInUOW_();
1743
1744    protected abstract boolean doCloseStatementsOnClose_();
1745
1746    public abstract SectionManager newSectionManager(String JavaDoc collection,
1747                                                     Agent agent,
1748                                                     String JavaDoc databaseName);
1749    //--------------------Abstract material factory methods-----------------
1750

1751    protected abstract Agent newAgent_(LogWriter logWriter, int loginTimeout, String JavaDoc serverName, int portNumber) throws SqlException;
1752
1753
1754    protected abstract DatabaseMetaData newDatabaseMetaData_();
1755
1756    protected abstract Statement newStatement_(int type,
1757                                               int concurrency,
1758                                               int holdability) throws SqlException;
1759
1760    protected abstract void resetStatement_(Statement statement,
1761                                            int type,
1762                                            int concurrency,
1763                                            int holdability) throws SqlException;
1764
1765
1766    protected abstract PreparedStatement newPositionedUpdatePreparedStatement_(String JavaDoc sql, Section section) throws SqlException;
1767
1768    protected abstract PreparedStatement newPreparedStatement_(String JavaDoc sql,
1769                                                               int type,
1770                                                               int concurrency,
1771                                                               int holdability,
1772                                                               int autoGeneratedKeys,
1773                                                               String JavaDoc[] columnNames) throws SqlException;
1774
1775    protected abstract void resetPreparedStatement_(PreparedStatement ps,
1776                                                    String JavaDoc sql,
1777                                                    int resultSetType,
1778                                                    int resultSetConcurrency,
1779                                                    int resultSetHoldability,
1780                                                    int autoGeneratedKeys,
1781                                                    String JavaDoc[] columnNames) throws SqlException;
1782
1783    protected abstract CallableStatement newCallableStatement_(String JavaDoc sql,
1784                                                               int type,
1785                                                               int concurrency,
1786                                                               int holdability) throws SqlException;
1787
1788    protected abstract void resetCallableStatement_(CallableStatement cs,
1789                                                    String JavaDoc sql,
1790                                                    int resultSetType,
1791                                                    int resultSetConcurrency,
1792                                                    int resultSetHoldability) throws SqlException;
1793
1794    // ----------------------- abstract box car and callback methods ---------------------
1795
// All callbacks must be client-side only operations.
1796

1797
1798    public void completeConnect() throws SqlException {
1799        open_ = true;
1800        databaseMetaData_ = newDatabaseMetaData_();
1801
1802        agent_.sectionManager_ =
1803                newSectionManager("NULLID",
1804                        agent_,
1805                        databaseName_);
1806        if (agent_.loggingEnabled()) {
1807            agent_.logWriter_.traceConnectExit(this);
1808        }
1809    }
1810
1811    public abstract void writeCommitSubstitute_() throws SqlException;
1812
1813    public abstract void readCommitSubstitute_() throws SqlException;
1814
1815    public abstract void writeLocalXAStart_() throws SqlException;
1816
1817    public abstract void readLocalXAStart_() throws SqlException;
1818
1819    public abstract void writeLocalXACommit_() throws SqlException;
1820    
1821    protected abstract void writeXACommit_() throws SqlException;
1822
1823    public abstract void readLocalXACommit_() throws SqlException;
1824    
1825    protected abstract void readXACommit_() throws SqlException;
1826
1827    public abstract void writeLocalCommit_() throws SqlException;
1828
1829    public abstract void readLocalCommit_() throws SqlException;
1830    
1831    protected abstract void writeXATransactionStart(Statement statement)
1832                                                throws SqlException;
1833
1834    public void completeLocalCommit() {
1835        java.util.Set JavaDoc keySet = CommitAndRollbackListeners_.keySet();
1836        for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
1837            UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1838            listener.completeLocalCommit(i);
1839        }
1840        inUnitOfWork_ = false;
1841    }
1842
1843    public abstract void writeLocalRollback_() throws SqlException;
1844
1845    public abstract void readLocalRollback_() throws SqlException;
1846
1847    // A callback for certain non-fatal exceptions that occur when parsing error replies.
1848
// This is a client-side only operation.
1849
// This method will only throw an exception on bug check.
1850
public void completeLocalRollback() {
1851        java.util.Set JavaDoc keySet = CommitAndRollbackListeners_.keySet();
1852        for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
1853            UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1854            listener.completeLocalRollback(i);
1855        }
1856        inUnitOfWork_ = false;
1857    }
1858    
1859    /**
1860     *
1861     * Rollback the specific UnitOfWorkListener.
1862     * @param uwl The UnitOfWorkLitener to be rolled back
1863     *
1864     */

1865    public void completeSpecificRollback(UnitOfWorkListener uwl) {
1866        java.util.Set JavaDoc keySet = CommitAndRollbackListeners_.keySet();
1867        for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
1868            UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1869            if(listener == uwl) {
1870                listener.completeLocalRollback(i);
1871                break;
1872            }
1873        }
1874        inUnitOfWork_ = false;
1875    }
1876
1877
1878    public abstract void writeLocalXARollback_() throws SqlException;
1879    
1880    protected abstract void writeXARollback_() throws SqlException;
1881
1882    public abstract void readLocalXARollback_() throws SqlException;
1883    
1884    protected abstract void readXARollback_() throws SqlException;
1885
1886    public void writeTransactionStart(Statement statement) throws SqlException {
1887        if (isXAConnection_) {
1888            writeXATransactionStart (statement);
1889        }
1890    }
1891
1892    public void readTransactionStart() throws SqlException {
1893        completeTransactionStart();
1894    }
1895
1896    void completeTransactionStart() {
1897        inUnitOfWork_ = true;
1898    }
1899
1900    // Occurs autonomously
1901
public void completeAbnormalUnitOfWork() {
1902        completeLocalRollback();
1903    }
1904    
1905    /**
1906     *
1907     * Rollback the UnitOfWorkListener specifically.
1908     * @param uwl The UnitOfWorkListener to be rolled back.
1909     *
1910     */

1911    public void completeAbnormalUnitOfWork(UnitOfWorkListener uwl) {
1912        completeSpecificRollback(uwl);
1913    }
1914
1915    // Called by Connection.close(), NetConnection.errorRollbackDisconnect().
1916
// The Agent's client-side resources associated with database connection are reclaimed (eg. socket).
1917
// And this connection and all associated statements and result sets are marked closed.
1918
// This is a client-side only operation.
1919
// This method will only throw an exception if the agent cannot be closed.
1920
public void completeChainBreakingDisconnect() {
1921        open_ = false;
1922        completeLocalRollback();
1923        markStatementsClosed();
1924    }
1925
1926    public void completeSqlca(Sqlca sqlca) {
1927        if (sqlca == null) {
1928        } else if (sqlca.getSqlCode() > 0) {
1929            accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca));
1930        } else if (sqlca.getSqlCode() < 0) {
1931            agent_.accumulateReadException(new SqlException(agent_.logWriter_, sqlca));
1932        }
1933    }
1934
1935    public abstract void addSpecialRegisters(String JavaDoc s);
1936
1937    // can this only be called by the PooledConnection
1938
// can this be called on a closed connection
1939
// can this be called in a unit of work
1940
// can this be called from within a stored procedure
1941
//
1942
synchronized public void reset(LogWriter logWriter, String JavaDoc user,
1943            String JavaDoc password, ClientBaseDataSource ds,
1944            boolean recomputeFromDataSource) throws SqlException {
1945        if (logWriter != null) {
1946            logWriter.traceConnectResetEntry(this, logWriter, user,
1947                                            (ds != null) ? ds : dataSource_);
1948        }
1949        try {
1950            reset_(logWriter, user, password, ds, recomputeFromDataSource);
1951        } catch (SqlException sqle) {
1952            DisconnectException de = new DisconnectException(agent_,
1953                new ClientMessageId(SQLState.CONNECTION_FAILED_ON_RESET));
1954            de.setNextException(sqle);
1955            throw de;
1956        }
1957    }
1958
1959    synchronized public void reset(LogWriter logWriter, ClientBaseDataSource ds,
1960            boolean recomputeFromDataSource) throws SqlException {
1961        if (logWriter != null) {
1962            logWriter.traceConnectResetEntry(this, logWriter, null, (ds != null) ? ds : dataSource_);
1963        }
1964        try {
1965            reset_(logWriter, ds, recomputeFromDataSource);
1966        } catch (SqlException sqle) {
1967            DisconnectException de = new DisconnectException(agent_,
1968                new ClientMessageId(SQLState.CONNECTION_FAILED_ON_RESET));
1969            de.setNextException(sqle);
1970            throw de;
1971        }
1972    }
1973
1974    synchronized public void lightReset() throws SqlException {
1975        if (!open_ && !availableForReuse_) {
1976            return;
1977        }
1978        open_ = true;
1979        availableForReuse_ = false;
1980    }
1981
1982    abstract protected void reset_(LogWriter logWriter, String JavaDoc user,
1983            String JavaDoc password, ClientBaseDataSource ds,
1984            boolean recomputerFromDataSource) throws SqlException;
1985
1986    abstract protected void reset_(LogWriter logWriter,
1987            ClientBaseDataSource ds,
1988            boolean recomputerFromDataSource) throws SqlException;
1989
1990    protected void completeReset(boolean isDeferredReset, boolean recomputeFromDataSource) throws SqlException {
1991        open_ = true;
1992
1993        completeLocalRollback(); // this will close the cursors if the physical connection hadn't been closed for reuse properly
1994

1995        // Reopen physical statement resources associated with previous uses of this physical connection.
1996
// Notice that these physical statements may not belong to this logical connection.
1997
// Iterate through the physical statements and re-enable them for reuse.
1998

1999        java.util.Set JavaDoc keySet = openStatements_.keySet();
2000        for (java.util.Iterator JavaDoc i = keySet.iterator(); i.hasNext();) {
2001            Object JavaDoc o = i.next();
2002            ((Statement) o).reset(recomputeFromDataSource);
2003
2004        }
2005
2006        if (!isDeferredReset && agent_.loggingEnabled()) {
2007            agent_.logWriter_.traceConnectResetExit(this);
2008        }
2009    }
2010
2011
2012    //-------------------------------helper methods-------------------------------
2013

2014    protected void checkForClosedConnection() throws SqlException {
2015        if (!open_) {
2016            agent_.checkForDeferredExceptions();
2017            throw new SqlException(agent_.logWriter_,
2018                    new ClientMessageId (SQLState.NO_CURRENT_CONNECTION));
2019        } else {
2020            agent_.checkForDeferredExceptions();
2021        }
2022    }
2023
2024    void checkAutoGeneratedKeysParameters(int autoGeneratedKeys, String JavaDoc[] columnNames) throws SqlException {
2025        if (autoGeneratedKeys != java.sql.Statement.NO_GENERATED_KEYS &&
2026                autoGeneratedKeys != java.sql.Statement.RETURN_GENERATED_KEYS) {
2027            throw new SqlException(agent_.logWriter_,
2028                    new ClientMessageId(SQLState.BAD_AUTO_GEN_KEY_VALUE),
2029                    new Integer JavaDoc (autoGeneratedKeys));
2030        }
2031
2032        if (columnNames != null) {
2033            throw new SqlException(agent_.logWriter_,
2034                    new ClientMessageId (SQLState.NOT_IMPLEMENTED),
2035                    "getAutoGeneratedKeys(columnNames == null)");
2036        }
2037
2038    }
2039
2040    public boolean isXAConnection() {
2041        return isXAConnection_;
2042    }
2043
2044    public int getXAState() {
2045        return xaState_;
2046    }
2047
2048    public void setXAState(int state) {
2049        xaState_ = state;
2050    }
2051
2052    public void accumulateWarning(SqlWarning e) {
2053        if (warnings_ == null) {
2054            warnings_ = e;
2055        } else {
2056            warnings_.setNextException(e);
2057        }
2058    }
2059
2060    public void accumulate440WarningForMessageProcFailure(SqlWarning e) {
2061        if (!accumulated440ForMessageProcFailure_) {
2062            accumulateWarning(e);
2063            accumulated440ForMessageProcFailure_ = true;
2064        }
2065    }
2066
2067    public void accumulate444WarningForMessageProcFailure(SqlWarning e) {
2068        if (!accumulated444ForMessageProcFailure_) {
2069            accumulateWarning(e);
2070            accumulated444ForMessageProcFailure_ = true;
2071        }
2072    }
2073
2074    // get the server version
2075
public int getServerVersion() {
2076        return databaseMetaData_.productLevel_.versionLevel_;
2077    }
2078
2079    public void setInUnitOfWork(boolean inUnitOfWork) {
2080        inUnitOfWork_ = inUnitOfWork;
2081    }
2082    
2083    /**
2084     * Return the holdabilty for the Connection. Matches the
2085     * embedded driver in the restriction that while in a
2086     * global (XA) transaction the holdability is CLOSE_CURSORS_AT_COMMIT.
2087     * Otherwise return the holdability set by the user.
2088     */

2089    final int holdability()
2090    {
2091        if (this.isXAConnection_ && this.xaState_ == XA_T1_ASSOCIATED)
2092            return JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
2093        return holdability;
2094    }
2095
2096}
2097
Popular Tags