0001: /*
0002:
0003: Derby - Class org.apache.derby.client.am.Connection
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.client.am;
0023:
0024: import org.apache.derby.jdbc.ClientBaseDataSource;
0025: import org.apache.derby.jdbc.ClientDataSource;
0026: import org.apache.derby.shared.common.reference.JDBC30Translation;
0027: import org.apache.derby.shared.common.reference.SQLState;
0028:
0029: import java.sql.SQLException;
0030:
0031: public abstract class Connection implements java.sql.Connection,
0032: ConnectionCallbackInterface {
0033: //---------------------navigational members-----------------------------------
0034:
0035: public Agent agent_;
0036:
0037: public DatabaseMetaData databaseMetaData_;
0038: // DERBY-210 - WeakHashMap is used to store references to objects to avoid
0039: // memory leaks. When there are no other references to the keys in a
0040: // WeakHashMap, they will get removed from the map and can thus get
0041: // garbage-collected. They do not have to wait till the Connection object
0042: // is collected.
0043:
0044: // In Connection.markStatementsClosed() method, this list is traversed to get a
0045: // list of open statements, which are marked closed and removed from the list.
0046: final java.util.WeakHashMap openStatements_ = new java.util.WeakHashMap();
0047:
0048: // Some statuses of DERBY objects may be invalid on server
0049: // after both commit and rollback. For example,
0050: // (1) prepared statements need to be re-prepared
0051: // after both commit and rollback
0052: // (2) result set will be unpositioned on server after both commit and rollback.
0053: // If they depend on both commit and rollback, they need to get on CommitAndRollbackListeners_.
0054: final java.util.WeakHashMap CommitAndRollbackListeners_ = new java.util.WeakHashMap();
0055: private SqlWarning warnings_ = null;
0056:
0057: // ------------------------properties set for life of connection--------------
0058:
0059: // See ClientDataSource pre-connect settings
0060: public transient String user_;
0061: public boolean retrieveMessageText_;
0062: protected boolean jdbcReadOnly_;
0063: /**
0064: * Holdabilty for created statements.
0065: * Only access through the holdability method
0066: * to ensure the correct value is returned for an
0067: * XA connection.
0068: */
0069: private int holdability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
0070:
0071: public String databaseName_;
0072:
0073: // Holds the Product-Specific Identifier which specifies
0074: // the product release level of a DDM Server.
0075: // The max length is 8.
0076: public String productID_;
0077:
0078: // Used to get the public key and encrypt password and/or userid
0079: protected EncryptionManager encryptionManager_;
0080:
0081: // used to set transaction isolation level
0082: private Statement setTransactionIsolationStmt = null;
0083:
0084: // used to get transaction isolation level
0085: private Statement getTransactionIsolationStmt = null;
0086:
0087: // ------------------------dynamic properties---------------------------------
0088:
0089: protected boolean open_ = true;
0090: protected boolean availableForReuse_ = false;
0091:
0092: public int isolation_ = Configuration.defaultIsolation;
0093: public boolean autoCommit_ = true;
0094: protected boolean inUnitOfWork_ = false; // This means a transaction is in progress.
0095:
0096: private boolean accumulated440ForMessageProcFailure_ = false;
0097: private boolean accumulated444ForMessageProcFailure_ = false;
0098: private boolean accumulatedSetReadOnlyWarning_ = false;
0099:
0100: //---------------------XA-----------------------------------------------------
0101:
0102: protected boolean isXAConnection_ = false; // Indicates an XA connection
0103:
0104: // XA States
0105: // The client needs to keep track of the connection's transaction branch association
0106: // per table 2.6 in the XA+ specification in order to determine if commits should flow in
0107: // autocommit mode. There is no need to keep track of suspended transactions separately from
0108: // XA_TO_NOT_ASSOCIATED.
0109: //
0110: /**
0111: * <code>XA_T0_NOT_ASSOCIATED</code>
0112: * This connection is not currently associated with an XA transaction
0113: * In this state commits will flow in autocommit mode.
0114: */
0115: public static final int XA_T0_NOT_ASSOCIATED = 0;
0116:
0117: /**
0118: * <code>XA_T1_ASSOCIATED</code>
0119: * In this state commits will not flow in autocommit mode.
0120: */
0121: public static final int XA_T1_ASSOCIATED = 1;
0122:
0123: //TODO: Remove XA_RECOVER entirely once indoubtlist is gone.
0124: //public static final int XA_RECOVER = 14;
0125:
0126: private int xaState_ = XA_T0_NOT_ASSOCIATED;
0127:
0128: // XA Host Type
0129: public int xaHostVersion_ = 0;
0130:
0131: public int loginTimeout_;
0132: public org.apache.derby.jdbc.ClientBaseDataSource dataSource_;
0133: public String serverNameIP_;
0134: public int portNumber_;
0135:
0136: public java.util.Hashtable clientCursorNameCache_ = new java.util.Hashtable();
0137: public boolean canUseCachedConnectBytes_ = false;
0138: public int commBufferSize_ = 32767;
0139:
0140: // indicates if a deferred reset connection is required
0141: public boolean resetConnectionAtFirstSql_ = false;
0142:
0143: //---------------------constructors/finalizer---------------------------------
0144:
0145: // For jdbc 2 connections
0146: protected Connection(
0147: org.apache.derby.client.am.LogWriter logWriter,
0148: String user, String password,
0149: org.apache.derby.jdbc.ClientBaseDataSource dataSource)
0150: throws SqlException {
0151: initConnection(logWriter, user, dataSource);
0152: }
0153:
0154: protected Connection(
0155: org.apache.derby.client.am.LogWriter logWriter,
0156: String user, String password, boolean isXAConn,
0157: org.apache.derby.jdbc.ClientBaseDataSource dataSource)
0158: throws SqlException {
0159: isXAConnection_ = isXAConn;
0160: initConnection(logWriter, user, dataSource);
0161: }
0162:
0163: // For jdbc 2 connections
0164: protected void initConnection(
0165: org.apache.derby.client.am.LogWriter logWriter,
0166: String user,
0167: org.apache.derby.jdbc.ClientBaseDataSource dataSource)
0168: throws SqlException {
0169: if (logWriter != null) {
0170: logWriter.traceConnectEntry(dataSource);
0171: }
0172:
0173: user_ = user;
0174:
0175: // Extract common properties.
0176: // Derby-409 fix - Append connectionAttributes only if it is non-null.
0177: // DERBY-1130 - Append connectionAttributes only if database name is
0178: // non-null. This will prevent use of database name set using
0179: // "setConnectionAttributes" method.
0180: databaseName_ = dataSource.getDatabaseName();
0181: String connAtrrs = dataSource.getConnectionAttributes();
0182: if (databaseName_ != null && connAtrrs != null)
0183: databaseName_ = databaseName_ + ";" + connAtrrs;
0184:
0185: retrieveMessageText_ = dataSource.getRetrieveMessageText();
0186:
0187: loginTimeout_ = dataSource.getLoginTimeout();
0188: dataSource_ = dataSource;
0189:
0190: serverNameIP_ = dataSource.getServerName();
0191: portNumber_ = dataSource.getPortNumber();
0192:
0193: agent_ = newAgent_(logWriter, loginTimeout_, serverNameIP_,
0194: portNumber_);
0195: }
0196:
0197: // For jdbc 2 connections
0198: protected Connection(
0199: org.apache.derby.client.am.LogWriter logWriter,
0200: boolean isXAConn,
0201: org.apache.derby.jdbc.ClientBaseDataSource dataSource)
0202: throws SqlException {
0203: if (logWriter != null) {
0204: logWriter.traceConnectEntry(dataSource);
0205: }
0206: isXAConnection_ = isXAConn;
0207:
0208: user_ = ClientDataSource.propertyDefault_user;
0209:
0210: // Extract common properties.
0211: databaseName_ = dataSource.getDatabaseName();
0212: retrieveMessageText_ = dataSource.getRetrieveMessageText();
0213:
0214: loginTimeout_ = dataSource.getLoginTimeout();
0215: dataSource_ = dataSource;
0216:
0217: serverNameIP_ = dataSource.getServerName();
0218: portNumber_ = dataSource.getPortNumber();
0219:
0220: agent_ = newAgent_(logWriter, loginTimeout_, serverNameIP_,
0221: portNumber_);
0222: }
0223:
0224: // This is a callback method, called by subsystem - NetConnection
0225: protected void resetConnection(LogWriter logWriter, String user,
0226: ClientBaseDataSource ds, boolean recomputeFromDataSource)
0227: throws SqlException {
0228: // clearWarningsX() will re-initialize the following properties
0229: clearWarningsX();
0230:
0231: user_ = (user != null) ? user : user_;
0232:
0233: if (ds != null && recomputeFromDataSource) { // no need to reinitialize connection state if ds hasn't changed
0234: user_ = (user != null) ? user : ds.getUser();
0235: ;
0236:
0237: retrieveMessageText_ = ds.getRetrieveMessageText();
0238:
0239: // property encryptionManager_
0240: // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
0241: encryptionManager_ = null;
0242:
0243: // property: open_
0244: // this should already be true
0245:
0246: isolation_ = Configuration.defaultIsolation;
0247: autoCommit_ = true;
0248: inUnitOfWork_ = false;
0249:
0250: loginTimeout_ = ds.getLoginTimeout();
0251: dataSource_ = ds;
0252:
0253: holdability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
0254: }
0255:
0256: if (recomputeFromDataSource) {
0257: this .agent_.resetAgent(this , logWriter, loginTimeout_,
0258: serverNameIP_, portNumber_);
0259: }
0260: }
0261:
0262: protected void resetConnection(LogWriter logWriter,
0263: String databaseName, java.util.Properties properties)
0264: throws SqlException {
0265: // clearWarningsX() will re-initialize the following properties
0266: // warnings_, accumulated440ForMessageProcFailure_,
0267: // accumulated444ForMessageProcFailure_, and accumulatedSetReadOnlyWarning_
0268: clearWarningsX();
0269:
0270: databaseName_ = databaseName;
0271: user_ = ClientDataSource.getUser(properties);
0272:
0273: retrieveMessageText_ = ClientDataSource
0274: .getRetrieveMessageText(properties);
0275:
0276: // property encryptionManager_
0277: // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
0278: encryptionManager_ = null;
0279:
0280: // property: open_
0281: // this should already be true
0282:
0283: isolation_ = Configuration.defaultIsolation;
0284: autoCommit_ = true;
0285: inUnitOfWork_ = false;
0286:
0287: this .agent_.resetAgent(this , logWriter, loginTimeout_,
0288: serverNameIP_, portNumber_);
0289:
0290: }
0291:
0292: // For jdbc 1 connections
0293: protected Connection(LogWriter logWriter,
0294: int driverManagerLoginTimeout, String serverName,
0295: int portNumber, String databaseName,
0296: java.util.Properties properties) throws SqlException {
0297: if (logWriter != null) {
0298: logWriter.traceConnectEntry(serverName, portNumber,
0299: databaseName, properties);
0300: }
0301:
0302: databaseName_ = databaseName;
0303:
0304: // Extract common properties.
0305: user_ = ClientDataSource.getUser(properties);
0306: retrieveMessageText_ = ClientDataSource
0307: .getRetrieveMessageText(properties);
0308:
0309: loginTimeout_ = driverManagerLoginTimeout;
0310: serverNameIP_ = serverName;
0311: portNumber_ = portNumber;
0312:
0313: agent_ = newAgent_(logWriter, loginTimeout_, serverNameIP_,
0314: portNumber_);
0315: }
0316:
0317: // Users are advised to call the method close() on Statement and Connection objects when they are done with them.
0318: // However, some users will forget, and some code may get killed before it can close these objects.
0319: // Therefore, if JDBC drivers have state associated with JDBC objects that need to get
0320: // explicitly cleared up, they should provide finalize methods to take care of them.
0321: // The garbage collector will call these finalize methods when the objects are found to be garbage,
0322: // and this will give the driver a chance to close (or otherwise clean up) the objects.
0323: // Note, however, that there is no guarantee that the garbage collector will ever run.
0324: // If that is the case, the finalizers will not be called.
0325: protected void finalize() throws java.lang.Throwable {
0326: if (agent_.loggingEnabled()) {
0327: agent_.logWriter_.traceEntry(this , "finalize");
0328: }
0329:
0330: // finalize() differs from close() in that it will not throw an
0331: // exception if a transaction is in progress.
0332: // finalize() also differs from close() in that it will not drive
0333: // an auto-commit before disconnecting.
0334: //
0335: // If a transaction is in progress, a close() request will throw an SqlException.
0336: // However, if a connection with an incomplete transaction is finalized,
0337: // or is abruptly terminated by application exit,
0338: // the normal rollback semantics imposed by the DERBY server are adopted.
0339: // So we just pull the plug and let the server handle this default semantic.
0340:
0341: if (!open_) {
0342: return;
0343: }
0344: agent_.disconnectEvent();
0345: super .finalize();
0346: }
0347:
0348: // ---------------------------jdbc 1------------------------------------------
0349:
0350: synchronized public java.sql.Statement createStatement()
0351: throws SQLException {
0352: try {
0353: if (agent_.loggingEnabled()) {
0354: agent_.logWriter_.traceEntry(this , "createStatement");
0355: }
0356: Statement s = createStatementX(
0357: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0358: java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
0359: if (agent_.loggingEnabled()) {
0360: agent_.logWriter_.traceExit(this , "createStatement", s);
0361: }
0362: return s;
0363: } catch (SqlException se) {
0364: throw se.getSQLException();
0365: }
0366: }
0367:
0368: synchronized public java.sql.PreparedStatement prepareStatement(
0369: String sql) throws SQLException {
0370: try {
0371: if (agent_.loggingEnabled()) {
0372: agent_.logWriter_.traceEntry(this , "prepareStatement",
0373: sql);
0374: }
0375: PreparedStatement ps = prepareStatementX(sql,
0376: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0377: java.sql.ResultSet.CONCUR_READ_ONLY, holdability(),
0378: java.sql.Statement.NO_GENERATED_KEYS, null);
0379: if (agent_.loggingEnabled()) {
0380: agent_.logWriter_.traceExit(this , "prepareStatement",
0381: ps);
0382: }
0383: return ps;
0384: } catch (SqlException se) {
0385: throw se.getSQLException();
0386: }
0387: }
0388:
0389: // For internal use only. Use by updatable result set code.
0390: synchronized public PreparedStatement preparePositionedUpdateStatement(
0391: String sql, Section querySection) throws SqlException {
0392: checkForClosedConnection();
0393: // create a net material prepared statement.
0394: PreparedStatement preparedStatement = newPositionedUpdatePreparedStatement_(
0395: sql, querySection);
0396: preparedStatement.flowPrepareDescribeInputOutput();
0397: // The positioned update statement is not added to the list of open statements,
0398: // because this would cause a java.util.ConcurrentModificationException when
0399: // iterating thru the list of open statements to call completeRollback().
0400: // An updatable result set is marked closed on a call to completeRollback(),
0401: // and would therefore need to close the positioned update statement associated with the result set which would cause
0402: // it to be removed from the open statements list. Resulting in concurrent modification
0403: // on the open statements list.
0404: // Notice that ordinary Statement.closeX() is never called on the positioned update statement,
0405: // rather markClosed() is called to avoid trying to remove the statement from the openStatements_ list.
0406: return preparedStatement;
0407: }
0408:
0409: synchronized public java.sql.CallableStatement prepareCall(
0410: String sql) throws SQLException {
0411: try {
0412: if (agent_.loggingEnabled()) {
0413: agent_.logWriter_.traceEntry(this , "prepareCall", sql);
0414: }
0415: CallableStatement cs = prepareCallX(sql,
0416: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0417: java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
0418: if (agent_.loggingEnabled()) {
0419: agent_.logWriter_.traceExit(this , "prepareCall", cs);
0420: }
0421: return cs;
0422: } catch (SqlException se) {
0423: throw se.getSQLException();
0424: }
0425: }
0426:
0427: synchronized PreparedStatement prepareDynamicCatalogQuery(String sql)
0428: throws SqlException {
0429: PreparedStatement ps = newPreparedStatement_(sql,
0430: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0431: java.sql.ResultSet.CONCUR_READ_ONLY, holdability(),
0432: java.sql.Statement.NO_GENERATED_KEYS, null);
0433: ps.isCatalogQuery_ = true;
0434: ps.prepare();
0435: openStatements_.put(ps, null);
0436: return ps;
0437: }
0438:
0439: public String nativeSQL(String sql) throws SQLException {
0440: try {
0441: if (agent_.loggingEnabled()) {
0442: agent_.logWriter_.traceEntry(this , "nativeSQL", sql);
0443: }
0444: String nativeSql = nativeSQLX(sql);
0445: if (agent_.loggingEnabled()) {
0446: agent_.logWriter_.traceExit(this , "nativeSQL",
0447: nativeSql);
0448: }
0449: return nativeSql;
0450: } catch (SqlException se) {
0451: throw se.getSQLException();
0452: }
0453:
0454: }
0455:
0456: synchronized public String nativeSQLX(String sql)
0457: throws SqlException {
0458: checkForClosedConnection();
0459: if (sql == null) {
0460: throw new SqlException(agent_.logWriter_,
0461: new ClientMessageId(SQLState.NULL_SQL_TEXT));
0462: }
0463:
0464: // Derby can handle the escape syntax directly so only needs escape
0465: // processing for { ? = CALL ....}
0466: String trimSql = sql.trim();
0467: if (trimSql.startsWith("{")) {
0468: if (trimSql.lastIndexOf("}") >= 0) {
0469: return trimSql.substring(1, trimSql.lastIndexOf("}"));
0470: }
0471: }
0472:
0473: return trimSql;
0474: }
0475:
0476: // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
0477: // primary usage is distinction between local and global trans. envs.;
0478: protected abstract boolean allowLocalCommitRollback_()
0479: throws org.apache.derby.client.am.SqlException;
0480:
0481: synchronized public void setAutoCommit(boolean autoCommit)
0482: throws SQLException {
0483: try {
0484: if (agent_.loggingEnabled()) {
0485: agent_.logWriter_.traceEntry(this , "setAutoCommit",
0486: autoCommit);
0487: }
0488: checkForClosedConnection();
0489:
0490: if (!allowLocalCommitRollback_()) {
0491: if (autoCommit) { // can't toggle to autocommit mode when between xars.start() and xars.end()
0492: throw new SqlException(
0493: agent_.logWriter_,
0494: new ClientMessageId(
0495: SQLState.DRDA_NO_AUTOCOMMIT_UNDER_XA));
0496: }
0497: } else {
0498: if (autoCommit == autoCommit_) {
0499: return; // don't flow a commit if nothing changed.
0500: }
0501: if (inUnitOfWork_) {
0502: flowCommit(); // we are not between xars.start() and xars.end(), can flow commit
0503: }
0504: }
0505: autoCommit_ = autoCommit;
0506: } catch (SqlException se) {
0507: throw se.getSQLException();
0508: }
0509: }
0510:
0511: public boolean getAutoCommit() throws SQLException {
0512: try {
0513: checkForClosedConnection();
0514: if (agent_.loggingEnabled()) {
0515: agent_.logWriter_.traceExit(this , "getAutoCommit",
0516: autoCommit_);
0517: }
0518: if (!allowLocalCommitRollback_()) { // autoCommit is always false between xars.start() and xars.end()
0519: return false;
0520: }
0521: return autoCommit_;
0522: } catch (SqlException se) {
0523: throw se.getSQLException();
0524: }
0525: }
0526:
0527: synchronized public void commit() throws SQLException {
0528: try {
0529: if (agent_.loggingEnabled()) {
0530: agent_.logWriter_.traceEntry(this , "commit");
0531: }
0532: checkForClosedConnection();
0533:
0534: // the following XA State check must be in commit instead of commitX since
0535: // external application call commit, the SqlException should be thrown
0536: // only if an external application calls commit during a Global Transaction,
0537: // internal code will call commitX which will ignore the commit request
0538: // while in a Global transaction
0539: checkForInvalidXAStateOnCommitOrRollback();
0540: flowCommit();
0541: } catch (SqlException se) {
0542: throw se.getSQLException();
0543: }
0544: }
0545:
0546: private void checkForInvalidXAStateOnCommitOrRollback()
0547: throws SqlException {
0548: if (!allowLocalCommitRollback_()) {
0549: throw new SqlException(
0550: agent_.logWriter_,
0551: new ClientMessageId(
0552: SQLState.DRDA_INVALID_XA_STATE_ON_COMMIT_OR_ROLLBACK));
0553: }
0554: }
0555:
0556: public void flowCommit() throws SqlException {
0557: // Per JDBC specification (see javadoc for Connection.commit()):
0558: // "This method should be used only when auto-commit mode has been disabled."
0559: // However, some applications do this anyway, it is harmless, so
0560: // if they ask to commit, we could go ahead and flow a commit.
0561: // But note that rollback() is less harmless, rollback() shouldn't be used in auto-commit mode.
0562: // This behavior is subject to further review.
0563:
0564: // if (!this.inUnitOfWork)
0565: // return;
0566: // We won't try to be "too smart", if the user requests a commit, we'll flow a commit,
0567: // regardless of whether or not we're in a unit of work or in auto-commit mode.
0568: //
0569: if (isXAConnection_) {
0570: agent_.beginWriteChainOutsideUOW();
0571: writeCommit();
0572: agent_.flowOutsideUOW();
0573: readCommit(); // This will invoke the commitEvent() callback from the material layer.
0574: agent_.endReadChain();
0575: } else {
0576: agent_.beginWriteChain(null);
0577: writeCommit();
0578: agent_.flow(null);
0579: readCommit(); // This will invoke the commitEvent() callback from the material layer.
0580: agent_.endReadChain();
0581: }
0582:
0583: }
0584:
0585: // precondition: autoCommit_ is true
0586: public boolean flowAutoCommit() throws SqlException {
0587: if (willAutoCommitGenerateFlow()) {
0588: flowCommit();
0589: return true;
0590: }
0591: return false;
0592: }
0593:
0594: public boolean willAutoCommitGenerateFlow()
0595: throws org.apache.derby.client.am.SqlException {
0596: if (!autoCommit_) {
0597: return false;
0598: }
0599: if (!allowLocalCommitRollback_()) {
0600: return false;
0601: }
0602: return true;
0603: }
0604:
0605: // precondition: autoCommit_ is true
0606: void writeAutoCommit() throws SqlException {
0607: if (willAutoCommitGenerateFlow()) {
0608: writeCommit();
0609: }
0610: }
0611:
0612: public void writeCommit() throws SqlException {
0613: if (isXAConnection_) {
0614: writeXACommit_();
0615: } else {
0616: writeLocalCommit_();
0617: }
0618: }
0619:
0620: // precondition: autoCommit_ is true
0621: void readAutoCommit() throws SqlException {
0622: if (willAutoCommitGenerateFlow()) {
0623: readCommit();
0624: }
0625: }
0626:
0627: public void readCommit() throws SqlException {
0628: if (isXAConnection_) {
0629: readXACommit_();
0630: } else {
0631: readLocalCommit_();
0632: }
0633: }
0634:
0635: synchronized public void rollback() throws SQLException {
0636: try {
0637: if (agent_.loggingEnabled()) {
0638: agent_.logWriter_.traceEntry(this , "rollback");
0639: }
0640:
0641: checkForClosedConnection();
0642: checkForInvalidXAStateOnCommitOrRollback();
0643:
0644: flowRollback();
0645: } catch (SqlException se) {
0646: throw se.getSQLException();
0647: }
0648: }
0649:
0650: // Even if we're not in a transaction, all open result sets will be closed.
0651: // So we could probably just return if we're not in a transaction
0652: // using the following code:
0653: // if (!this.inUnitOfWork)
0654: // return;
0655: // But we'll just play it safe, and blindly flow the rollback.
0656: // We won't try to be "too smart", if the user requests a rollback, we'll flow a rollback,
0657: // regardless of whether or not we're in a unit of work or in auto-commit mode.
0658: //
0659: // Per JDBC specification (see javadoc for Connection.rollback()):
0660: // "This method should be used only when auto-commit mode has been disabled."
0661: // However, rather than trying to be too smart, we'll just flow the rollback anyway
0662: // before throwing an exception.
0663: // As a side-effect of invoking rollback() in auto-commit mode,
0664: // we'll close all open result sets on this connection in the rollbackEvent().
0665: //
0666: protected void flowRollback() throws SqlException {
0667: if (isXAConnection_) {
0668: agent_.beginWriteChainOutsideUOW();
0669: writeRollback();
0670: agent_.flowOutsideUOW();
0671: readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
0672: agent_.endReadChain();
0673: } else {
0674: agent_.beginWriteChain(null);
0675: writeRollback();
0676: agent_.flow(null);
0677: readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
0678: agent_.endReadChain();
0679: }
0680: }
0681:
0682: public void writeRollback() throws SqlException {
0683: if (isXAConnection_) {
0684: writeXARollback_();
0685: } else {
0686: writeLocalRollback_();
0687: }
0688: }
0689:
0690: public void readRollback() throws SqlException {
0691: if (isXAConnection_) {
0692: readLocalXARollback_();
0693: } else {
0694: readLocalRollback_();
0695: }
0696: }
0697:
0698: synchronized public void close() throws SQLException {
0699: if (agent_.loggingEnabled()) {
0700: agent_.logWriter_.traceEntry(this , "close");
0701: }
0702: closeX();
0703: }
0704:
0705: void checkForTransactionInProgress() throws SqlException {
0706: // The following precondition matches CLI semantics, see SQLDisconnect()
0707: if (transactionInProgress() && !allowCloseInUOW_()) {
0708: throw new SqlException(agent_.logWriter_,
0709: new ClientMessageId(
0710: SQLState.CANNOT_CLOSE_ACTIVE_CONNECTION));
0711: }
0712: }
0713:
0714: public boolean transactionInProgress() {
0715: return !autoCommit_ && inUnitOfWork_;
0716: }
0717:
0718: // This is a no-op if the connection is already closed.
0719: synchronized public void closeX() throws SQLException {
0720: if (!open_) {
0721: return;
0722: }
0723: closeResourcesX();
0724: }
0725:
0726: // Close physical socket or attachment even if connection is marked close.
0727: // Used by ClientPooledConnection.close().
0728: synchronized public void closeResources() throws SQLException {
0729: if (open_ || (!open_ && availableForReuse_)) {
0730: availableForReuse_ = false;
0731: closeResourcesX();
0732: }
0733: }
0734:
0735: private void closeResourcesX() throws SQLException {
0736: try {
0737: checkForTransactionInProgress();
0738: } catch (SqlException e) {
0739: throw e.getSQLException();
0740: }
0741:
0742: resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
0743: SQLException accumulatedExceptions = null;
0744: if (setTransactionIsolationStmt != null) {
0745: try {
0746: setTransactionIsolationStmt.close();
0747: } catch (SQLException se) {
0748: accumulatedExceptions = se;
0749: }
0750: }
0751: setTransactionIsolationStmt = null;
0752: if (getTransactionIsolationStmt != null) {
0753: try {
0754: getTransactionIsolationStmt.close();
0755: } catch (SQLException se) {
0756: accumulatedExceptions = Utils.accumulateSQLException(
0757: se, accumulatedExceptions);
0758: }
0759: }
0760: getTransactionIsolationStmt = null;
0761: try {
0762: flowClose();
0763: } catch (SqlException e) {
0764: accumulatedExceptions = Utils.accumulateSQLException(e
0765: .getSQLException(), accumulatedExceptions);
0766: }
0767:
0768: markClosed();
0769: try {
0770: agent_.close();
0771: } catch (SqlException e) {
0772: throw Utils.accumulateSQLException(e.getSQLException(),
0773: accumulatedExceptions);
0774: }
0775: }
0776:
0777: protected abstract boolean isGlobalPending_();
0778:
0779: // Just like closeX except the socket is not pulled.
0780: // Physical resources are not closed.
0781: synchronized public void closeForReuse() throws SqlException {
0782: if (!open_) {
0783: return;
0784: }
0785: resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
0786: SqlException accumulatedExceptions = null;
0787: try {
0788: flowClose();
0789: } catch (SqlException e) {
0790: accumulatedExceptions = e;
0791: }
0792: if (open_) {
0793: markClosedForReuse();
0794: }
0795: if (accumulatedExceptions != null) {
0796: throw accumulatedExceptions;
0797: }
0798: }
0799:
0800: private void flowClose() throws SqlException {
0801: agent_.beginWriteChainOutsideUOW();
0802: if (doCloseStatementsOnClose_()) {
0803: writeCloseStatements();
0804: }
0805: if (autoCommit_) {
0806: writeAutoCommit();
0807: }
0808: agent_.flowOutsideUOW();
0809: if (doCloseStatementsOnClose_()) {
0810: readCloseStatements();
0811: }
0812: if (autoCommit_) {
0813: readAutoCommit();
0814: }
0815: agent_.endReadChain();
0816: }
0817:
0818: protected abstract void markClosed_();
0819:
0820: public void markClosed() // called by LogicalConnection.close()
0821: {
0822: open_ = false;
0823: inUnitOfWork_ = false;
0824: markStatementsClosed();
0825: CommitAndRollbackListeners_.clear();
0826: markClosed_();
0827: }
0828:
0829: private void markClosedForReuse() {
0830: availableForReuse_ = true;
0831: markClosed();
0832: }
0833:
0834: private void markStatementsClosed() {
0835: java.util.Set keySet = openStatements_.keySet();
0836: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
0837: Statement stmt = (Statement) i.next();
0838: stmt.markClosed();
0839: i.remove();
0840: }
0841: }
0842:
0843: private void writeCloseStatements() throws SqlException {
0844: java.util.Set keySet = openStatements_.keySet();
0845: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
0846: ((Statement) i.next()).writeClose(false); // false means don't permit auto-commits
0847: }
0848: }
0849:
0850: private void readCloseStatements() throws SqlException {
0851: java.util.Set keySet = openStatements_.keySet();
0852: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
0853: ((Statement) i.next()).readClose(false); // false means don't permit auto-commits
0854: }
0855: }
0856:
0857: /**
0858: * Return true if the physical connection is still open.
0859: * Might be logically closed but available for reuse.
0860: * @return true if physical connection still open
0861: */
0862: public boolean isPhysicalConnClosed() {
0863: return !open_ && !availableForReuse_;
0864: }
0865:
0866: public boolean isClosed() {
0867: if (agent_.loggingEnabled()) {
0868: agent_.logWriter_.traceExit(this , "isClosed", !open_);
0869: }
0870: return !open_;
0871: }
0872:
0873: public boolean isClosedX() {
0874: return !open_;
0875: }
0876:
0877: private static String DERBY_TRANSACTION_REPEATABLE_READ = "RS";
0878: private static String DERBY_TRANSACTION_SERIALIZABLE = "RR";
0879: private static String DERBY_TRANSACTION_READ_COMMITTED = "CS";
0880: private static String DERBY_TRANSACTION_READ_UNCOMMITTED = "UR";
0881:
0882: synchronized public void setTransactionIsolation(int level)
0883: throws SQLException {
0884: try {
0885: if (agent_.loggingEnabled()) {
0886: agent_.logWriter_.traceEntry(this ,
0887: "setTransactionIsolation", level);
0888: }
0889: // Per jdbc spec (see java.sql.Connection.close() javadoc).
0890: checkForClosedConnection();
0891:
0892: // Javadoc for this method:
0893: // If this method is called during a transaction, the result is implementation-defined.
0894: //
0895: //
0896: // REPEATABLE_READ = JDBC: TRANSACTION_SERIALIZABLE, DERBY: RR, PROTOCOL: repeatable read
0897: // READ_STABILITY = JDBC: TRANSACTION_REPEATABLE_READ, DERBY: RS, PROTOCOL: All
0898: // CURSOR_STABILITY = JDBC: TRANSACTION_READ_COMMITTED, DERBY: CS, PROTOCOL: Cursor stability
0899: // UNCOMMITTED_READ = JDBC: TRANSACTION_READ_UNCOMMITTED, DERBY: UR , PROTOCOL: Change
0900: // NO_COMMIT = JDBC: TRANSACTION_NONE, DERBY: NC, PROTOCOL: No commit
0901: //
0902: String levelString = null;
0903: switch (level) {
0904: case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
0905: levelString = DERBY_TRANSACTION_REPEATABLE_READ;
0906: break;
0907: case java.sql.Connection.TRANSACTION_READ_COMMITTED:
0908: levelString = DERBY_TRANSACTION_READ_COMMITTED;
0909: break;
0910: case java.sql.Connection.TRANSACTION_SERIALIZABLE:
0911: levelString = DERBY_TRANSACTION_SERIALIZABLE;
0912: break;
0913: case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
0914: levelString = DERBY_TRANSACTION_READ_UNCOMMITTED;
0915: break;
0916: // Per javadoc:
0917: // Note that Connection.TRANSACTION_NONE cannot be used because it specifies that transactions are not supported.
0918: case java.sql.Connection.TRANSACTION_NONE:
0919: default:
0920: throw new SqlException(
0921: agent_.logWriter_,
0922: new ClientMessageId(
0923: SQLState.UNIMPLEMENTED_ISOLATION_LEVEL),
0924: new Integer(level));
0925: }
0926: if (setTransactionIsolationStmt == null
0927: || !(setTransactionIsolationStmt.openOnClient_ && setTransactionIsolationStmt.openOnServer_)) {
0928: setTransactionIsolationStmt = createStatementX(
0929: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0930: java.sql.ResultSet.CONCUR_READ_ONLY,
0931: holdability());
0932: }
0933:
0934: setTransactionIsolationStmt
0935: .executeUpdate("SET CURRENT ISOLATION = "
0936: + levelString);
0937:
0938: // The server has now implicitely committed the
0939: // transaction so we have to clean up locally.
0940: completeLocalCommit();
0941:
0942: isolation_ = level;
0943: } catch (SqlException se) {
0944: throw se.getSQLException();
0945: }
0946: }
0947:
0948: public int getTransactionIsolation() throws SQLException {
0949:
0950: // Store the current auto-commit value and use it to restore
0951: // at the end of this method.
0952: boolean currentAutoCommit = autoCommit_;
0953: java.sql.ResultSet rs = null;
0954:
0955: try {
0956: checkForClosedConnection();
0957: if (agent_.loggingEnabled()) {
0958: agent_.logWriter_.traceExit(this ,
0959: "getTransactionIsolation", isolation_);
0960: }
0961:
0962: // Set auto-commit to false when executing the statement as we do not want to
0963: // cause an auto-commit from getTransactionIsolation() method.
0964: autoCommit_ = false;
0965:
0966: // DERBY-1148 - Client reports wrong isolation level. We need to get the isolation
0967: // level from the server. 'isolation_' maintained in the client's connection object
0968: // can be out of sync with the real isolation when in an XA transaction. This can
0969: // also happen when isolation is set using SQL instead of JDBC. So we try to get the
0970: // value from the server by calling the "current isolation" function. If we fail to
0971: // get the value, return the value stored in the client's connection object.
0972: if (getTransactionIsolationStmt == null
0973: || !(getTransactionIsolationStmt.openOnClient_ && getTransactionIsolationStmt.openOnServer_)) {
0974: getTransactionIsolationStmt = createStatementX(
0975: java.sql.ResultSet.TYPE_FORWARD_ONLY,
0976: java.sql.ResultSet.CONCUR_READ_ONLY,
0977: holdability());
0978: }
0979:
0980: boolean savedInUnitOfWork = inUnitOfWork_;
0981: rs = getTransactionIsolationStmt
0982: .executeQuery("values current isolation");
0983: rs.next();
0984: String isolationStr = rs.getString(1);
0985: isolation_ = translateIsolation(isolationStr);
0986: rs.close();
0987: // So... of we did not have an active transaction before
0988: // the query, we pretend to still not have an open
0989: // transaction. The result set is closed, so this should
0990: // not be problematic. DERBY-2084
0991: inUnitOfWork_ = savedInUnitOfWork;
0992: } catch (SqlException se) {
0993: throw se.getSQLException();
0994: } finally {
0995: // Restore auto-commit value
0996: autoCommit_ = currentAutoCommit;
0997: if (rs != null)
0998: rs.close();
0999: }
1000:
1001: return isolation_;
1002: }
1003:
1004: /**
1005: * Translates the isolation level from a SQL string to the JDBC int value
1006: *
1007: * @param isolationStr SQL isolation string
1008: * @return isolation level as a JDBC integer value
1009: */
1010: private int translateIsolation(String isolationStr) {
1011: if (isolationStr.compareTo(DERBY_TRANSACTION_REPEATABLE_READ) == 0)
1012: return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
1013: else if (isolationStr.compareTo(DERBY_TRANSACTION_SERIALIZABLE) == 0)
1014: return java.sql.Connection.TRANSACTION_SERIALIZABLE;
1015: else if (isolationStr
1016: .compareTo(DERBY_TRANSACTION_READ_COMMITTED) == 0)
1017: return java.sql.Connection.TRANSACTION_READ_COMMITTED;
1018: else if (isolationStr
1019: .compareTo(DERBY_TRANSACTION_READ_UNCOMMITTED) == 0)
1020: return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
1021: else
1022: return java.sql.Connection.TRANSACTION_NONE;
1023: }
1024:
1025: public java.sql.SQLWarning getWarnings() throws SQLException {
1026: if (agent_.loggingEnabled()) {
1027: agent_.logWriter_.traceExit(this , "getWarnings", warnings_);
1028: }
1029: try {
1030: checkForClosedConnection();
1031: } catch (SqlException se) {
1032: throw se.getSQLException();
1033: }
1034: return warnings_ == null ? null : warnings_.getSQLWarning();
1035: }
1036:
1037: synchronized public void clearWarnings() throws SQLException {
1038: try {
1039: if (agent_.loggingEnabled()) {
1040: agent_.logWriter_.traceEntry(this , "clearWarnings");
1041: }
1042: checkForClosedConnection();
1043: clearWarningsX();
1044: } catch (SqlException se) {
1045: throw se.getSQLException();
1046: }
1047: }
1048:
1049: // An untraced version of clearWarnings()
1050: public void clearWarningsX() throws SqlException {
1051: warnings_ = null;
1052: accumulated440ForMessageProcFailure_ = false;
1053: accumulated444ForMessageProcFailure_ = false;
1054: accumulatedSetReadOnlyWarning_ = false;
1055: }
1056:
1057: //======================================================================
1058: // Advanced features:
1059:
1060: public java.sql.DatabaseMetaData getMetaData() throws SQLException {
1061: try {
1062: checkForClosedConnection();
1063: if (agent_.loggingEnabled()) {
1064: agent_.logWriter_.traceExit(this , "getMetaData",
1065: databaseMetaData_);
1066: }
1067: return databaseMetaData_;
1068: } catch (SqlException se) {
1069: throw se.getSQLException();
1070: }
1071: }
1072:
1073: synchronized public void setReadOnly(boolean readOnly)
1074: throws SQLException {
1075: try {
1076: // This is a hint to the driver only, so this request is silently ignored.
1077: // PROTOCOL can only flow a set-read-only before the connection is established.
1078: if (agent_.loggingEnabled()) {
1079: agent_.logWriter_.traceEntry(this , "setReadOnly",
1080: readOnly);
1081: }
1082: checkForClosedConnection();
1083: } catch (SqlException se) {
1084: throw se.getSQLException();
1085: }
1086: }
1087:
1088: public boolean isReadOnly() throws SQLException {
1089: try {
1090: checkForClosedConnection();
1091: if (agent_.loggingEnabled()) {
1092: agent_.logWriter_.traceExit(this , "isReadOnly",
1093: jdbcReadOnly_);
1094: }
1095: return false;
1096: } catch (SqlException se) {
1097: throw se.getSQLException();
1098: }
1099: }
1100:
1101: synchronized public void setCatalog(String catalog)
1102: throws SQLException {
1103: try {
1104: if (agent_.loggingEnabled()) {
1105: agent_.logWriter_.traceEntry(this , "setCatalog",
1106: catalog);
1107: }
1108: checkForClosedConnection();
1109: // Per jdbc spec: if the driver does not support catalogs, it will silently ignore this request.
1110: } catch (SqlException se) {
1111: throw se.getSQLException();
1112: }
1113: }
1114:
1115: public String getCatalog() throws SQLException {
1116: try {
1117: checkForClosedConnection();
1118: if (agent_.loggingEnabled()) {
1119: agent_.logWriter_.traceExit(this , "getCatalog",
1120: (String) null);
1121: }
1122: return null;
1123: } catch (SqlException se) {
1124: throw se.getSQLException();
1125: }
1126: }
1127:
1128: //--------------------------JDBC 2.0-----------------------------
1129:
1130: synchronized public java.sql.Statement createStatement(
1131: int resultSetType, int resultSetConcurrency)
1132: throws SQLException {
1133: try {
1134: if (agent_.loggingEnabled()) {
1135: agent_.logWriter_.traceEntry(this , "createStatement",
1136: resultSetType, resultSetConcurrency);
1137: }
1138: Statement s = createStatementX(resultSetType,
1139: resultSetConcurrency, holdability());
1140: if (agent_.loggingEnabled()) {
1141: agent_.logWriter_.traceExit(this , "createStatement", s);
1142: }
1143: return s;
1144: } catch (SqlException se) {
1145: throw se.getSQLException();
1146: }
1147: }
1148:
1149: synchronized public java.sql.PreparedStatement prepareStatement(
1150: String sql, int resultSetType, int resultSetConcurrency)
1151: throws SQLException {
1152: try {
1153: if (agent_.loggingEnabled()) {
1154: agent_.logWriter_.traceEntry(this , "prepareStatement",
1155: sql, resultSetType, resultSetConcurrency);
1156: }
1157: PreparedStatement ps = prepareStatementX(sql,
1158: resultSetType, resultSetConcurrency, holdability(),
1159: java.sql.Statement.NO_GENERATED_KEYS, null);
1160: if (agent_.loggingEnabled()) {
1161: agent_.logWriter_.traceExit(this , "prepareStatement",
1162: ps);
1163: }
1164: return ps;
1165: } catch (SqlException se) {
1166: throw se.getSQLException();
1167: }
1168: }
1169:
1170: synchronized public java.sql.CallableStatement prepareCall(
1171: String sql, int resultSetType, int resultSetConcurrency)
1172: throws SQLException {
1173: try {
1174: if (agent_.loggingEnabled()) {
1175: agent_.logWriter_.traceEntry(this , "prepareCall", sql,
1176: resultSetType, resultSetConcurrency);
1177: }
1178: CallableStatement cs = prepareCallX(sql, resultSetType,
1179: resultSetConcurrency, holdability());
1180: if (agent_.loggingEnabled()) {
1181: agent_.logWriter_.traceExit(this , "prepareCall", cs);
1182: }
1183: return cs;
1184: } catch (SqlException se) {
1185: throw se.getSQLException();
1186: }
1187: }
1188:
1189: synchronized public CallableStatement prepareMessageProc(String sql)
1190: throws SqlException {
1191: checkForClosedConnection();
1192:
1193: CallableStatement cs = prepareCallX(sql,
1194: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1195: java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
1196: return cs;
1197: }
1198:
1199: // Per jdbc spec, when a result set type is unsupported, we downgrade and
1200: // issue a warning rather than to throw an exception.
1201: private int downgradeResultSetType(int resultSetType) {
1202: if (resultSetType == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE) {
1203: accumulateWarning(new SqlWarning(agent_.logWriter_,
1204: new ClientMessageId(
1205: SQLState.SCROLL_SENSITIVE_NOT_SUPPORTED)));
1206: return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
1207: }
1208: return resultSetType;
1209: }
1210:
1211: public java.util.Map getTypeMap() throws SQLException {
1212: try {
1213: if (agent_.loggingEnabled()) {
1214: agent_.logWriter_.traceEntry(this , "getTypeMap");
1215: }
1216: checkForClosedConnection();
1217: java.util.Map map = new java.util.HashMap();
1218: if (agent_.loggingEnabled()) {
1219: agent_.logWriter_.traceExit(this , "getTypeMap", map);
1220: }
1221: return map;
1222: } catch (SqlException se) {
1223: throw se.getSQLException();
1224: }
1225: }
1226:
1227: synchronized public void setTypeMap(java.util.Map map)
1228: throws SQLException {
1229: try {
1230: if (agent_.loggingEnabled()) {
1231: agent_.logWriter_.traceEntry(this , "setTypeMap", map);
1232: }
1233: checkForClosedConnection();
1234: throw new SqlException(agent_.logWriter_,
1235: new ClientMessageId(SQLState.NOT_IMPLEMENTED),
1236: "setTypeMap");
1237: } catch (SqlException se) {
1238: throw se.getSQLException();
1239: }
1240: }
1241:
1242: //--------------------------JDBC 3.0-----------------------------
1243:
1244: synchronized public void setHoldability(int holdability)
1245: throws SQLException {
1246: try {
1247: if (agent_.loggingEnabled()) {
1248: agent_.logWriter_.traceEntry(this , "setHoldability",
1249: holdability);
1250: }
1251: checkForClosedConnection();
1252: // In an XA global transaction do not allow the
1253: // holdability to be set to hold cursors across
1254: // commits, as the engine does not support it.
1255: if (this .isXAConnection_
1256: && this .xaState_ == XA_T1_ASSOCIATED) {
1257: if (holdability == JDBC30Translation.HOLD_CURSORS_OVER_COMMIT)
1258: throw new SqlException(agent_.logWriter_,
1259: new ClientMessageId(
1260: SQLState.CANNOT_HOLD_CURSOR_XA));
1261: }
1262: this .holdability = holdability;
1263:
1264: } catch (SqlException se) {
1265: throw se.getSQLException();
1266: }
1267: }
1268:
1269: public int getHoldability() throws SQLException {
1270: try {
1271: checkForClosedConnection();
1272: if (agent_.loggingEnabled()) {
1273: agent_.logWriter_.traceExit(this , "getHoldability",
1274: holdability());
1275: }
1276: return holdability();
1277: } catch (SqlException se) {
1278: throw se.getSQLException();
1279: }
1280: }
1281:
1282: public int dncGeneratedSavepointId_;
1283: // generated name used internally for unnamed savepoints
1284: public static final String dncGeneratedSavepointNamePrefix__ = "DNC_GENENERATED_NAME_";
1285:
1286: synchronized public java.sql.Savepoint setSavepoint()
1287: throws SQLException {
1288: try {
1289: if (agent_.loggingEnabled()) {
1290: agent_.logWriter_.traceEntry(this , "setSavepoint");
1291: }
1292: checkForClosedConnection();
1293: if (autoCommit_) // Throw exception if auto-commit is on
1294: {
1295: throw new SqlException(agent_.logWriter_,
1296: new ClientMessageId(
1297: SQLState.NO_SAVEPOINT_WHEN_AUTO));
1298: }
1299: // create an un-named savepoint.
1300: if ((++dncGeneratedSavepointId_) < 0) {
1301: dncGeneratedSavepointId_ = 1; // restart from 1 when overflow.
1302: }
1303: Object s = setSavepointX(new Savepoint(agent_,
1304: dncGeneratedSavepointId_));
1305: return (java.sql.Savepoint) s;
1306: } catch (SqlException se) {
1307: throw se.getSQLException();
1308: }
1309: }
1310:
1311: synchronized public java.sql.Savepoint setSavepoint(String name)
1312: throws SQLException {
1313: try {
1314: if (agent_.loggingEnabled()) {
1315: agent_.logWriter_
1316: .traceEntry(this , "setSavepoint", name);
1317: }
1318: checkForClosedConnection();
1319: if (name == null) // Throw exception if savepoint name is null
1320: {
1321: throw new SqlException(agent_.logWriter_,
1322: new ClientMessageId(
1323: SQLState.NULL_NAME_FOR_SAVEPOINT));
1324: } else if (autoCommit_) // Throw exception if auto-commit is on
1325: {
1326: throw new SqlException(agent_.logWriter_,
1327: new ClientMessageId(
1328: SQLState.NO_SAVEPOINT_WHEN_AUTO));
1329: }
1330: // create a named savepoint.
1331: Object s = setSavepointX(new Savepoint(agent_, name));
1332: return (java.sql.Savepoint) s;
1333: } catch (SqlException se) {
1334: throw se.getSQLException();
1335: }
1336: }
1337:
1338: private Savepoint setSavepointX(Savepoint savepoint)
1339: throws SQLException {
1340: // Construct and flow a savepoint statement to server.
1341: Statement stmt = null;
1342: try {
1343: stmt = (Statement) createStatementX(
1344: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1345: java.sql.ResultSet.CONCUR_READ_ONLY, holdability());
1346: String savepointName;
1347: try {
1348: savepointName = savepoint.getSavepointName();
1349: } catch (SQLException e) {
1350: // generate the name for an un-named savepoint.
1351: savepointName = dncGeneratedSavepointNamePrefix__
1352: + savepoint.getSavepointId();
1353: }
1354: String sql = "SAVEPOINT \"" + savepointName
1355: + "\" ON ROLLBACK RETAIN CURSORS";
1356: stmt.executeX(sql);
1357: } catch (SqlException se) {
1358: throw se.getSQLException();
1359: } finally {
1360: if (stmt != null) {
1361: try {
1362: stmt.closeX();
1363: } catch (SqlException doNothing) {
1364: }
1365: }
1366: }
1367:
1368: return savepoint;
1369: }
1370:
1371: synchronized public void rollback(java.sql.Savepoint savepoint)
1372: throws SQLException {
1373: try {
1374: int saveXaState = xaState_;
1375: if (agent_.loggingEnabled()) {
1376: agent_.logWriter_.traceEntry(this , "rollback",
1377: savepoint);
1378: }
1379: checkForClosedConnection();
1380: if (savepoint == null) // Throw exception if savepoint is null
1381: {
1382: throw new SqlException(
1383: agent_.logWriter_,
1384: new ClientMessageId(
1385: SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL));
1386: } else if (autoCommit_) // Throw exception if auto-commit is on
1387: {
1388: throw new SqlException(
1389: agent_.logWriter_,
1390: new ClientMessageId(
1391: SQLState.NO_SAVEPOINT_ROLLBACK_OR_RELEASE_WHEN_AUTO));
1392: }
1393: // Only allow to rollback to a savepoint from the connection that create the savepoint.
1394: try {
1395: if (this != ((Savepoint) savepoint).agent_.connection_) {
1396: throw new SqlException(
1397: agent_.logWriter_,
1398: new ClientMessageId(
1399: SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1400: }
1401: } catch (java.lang.ClassCastException e) { // savepoint is not an instance of am.Savepoint
1402: throw new SqlException(
1403: agent_.logWriter_,
1404: new ClientMessageId(
1405: SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1406: }
1407:
1408: // Construct and flow a savepoint rollback statement to server.
1409: Statement stmt = null;
1410: try {
1411: stmt = createStatementX(
1412: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1413: java.sql.ResultSet.CONCUR_READ_ONLY,
1414: holdability());
1415: String savepointName;
1416: try {
1417: savepointName = ((Savepoint) savepoint)
1418: .getSavepointName();
1419: } catch (SQLException e) {
1420: // generate the name for an un-named savepoint.
1421: savepointName = dncGeneratedSavepointNamePrefix__
1422: + ((Savepoint) savepoint).getSavepointId();
1423: }
1424: String sql = "ROLLBACK TO SAVEPOINT \"" + savepointName
1425: + "\"";
1426: stmt.executeX(sql);
1427: } finally {
1428: if (stmt != null) {
1429: try {
1430: stmt.closeX();
1431: } catch (SqlException doNothing) {
1432: }
1433: }
1434: xaState_ = saveXaState;
1435: }
1436: } catch (SqlException se) {
1437: throw se.getSQLException();
1438: }
1439: }
1440:
1441: synchronized public void releaseSavepoint(
1442: java.sql.Savepoint savepoint) throws SQLException {
1443: try {
1444: int saveXaState = xaState_;
1445: if (agent_.loggingEnabled()) {
1446: agent_.logWriter_.traceEntry(this , "releaseSavepoint",
1447: savepoint);
1448: }
1449: checkForClosedConnection();
1450: if (savepoint == null) // Throw exception if savepoint is null
1451: {
1452: throw new SqlException(
1453: agent_.logWriter_,
1454: new ClientMessageId(
1455: SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL));
1456: } else if (autoCommit_) // Throw exception if auto-commit is on
1457: {
1458: throw new SqlException(
1459: agent_.logWriter_,
1460: new ClientMessageId(
1461: SQLState.NO_SAVEPOINT_ROLLBACK_OR_RELEASE_WHEN_AUTO));
1462: }
1463: // Only allow to release a savepoint from the connection that create the savepoint.
1464: try {
1465: if (this != ((Savepoint) savepoint).agent_.connection_) {
1466: throw new SqlException(
1467: agent_.logWriter_,
1468: new ClientMessageId(
1469: SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1470: }
1471: } catch (java.lang.ClassCastException e) { // savepoint is not an instance of am.Savepoint
1472: throw new SqlException(
1473: agent_.logWriter_,
1474: new ClientMessageId(
1475: SQLState.SAVEPOINT_NOT_CREATED_BY_CONNECTION));
1476:
1477: }
1478:
1479: // Construct and flow a savepoint release statement to server.
1480: Statement stmt = null;
1481: try {
1482: stmt = (Statement) createStatementX(
1483: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1484: java.sql.ResultSet.CONCUR_READ_ONLY,
1485: holdability());
1486: String savepointName;
1487: try {
1488: savepointName = ((Savepoint) savepoint)
1489: .getSavepointName();
1490: } catch (SQLException e) {
1491: // generate the name for an un-named savepoint.
1492: savepointName = dncGeneratedSavepointNamePrefix__
1493: + ((Savepoint) savepoint).getSavepointId();
1494: }
1495: String sql = "RELEASE SAVEPOINT \"" + savepointName
1496: + "\"";
1497: stmt.executeX(sql);
1498: } finally {
1499: if (stmt != null) {
1500: try {
1501: stmt.closeX();
1502: } catch (SqlException doNothing) {
1503: }
1504: }
1505: xaState_ = saveXaState;
1506: }
1507: } catch (SqlException se) {
1508: throw se.getSQLException();
1509: }
1510: }
1511:
1512: synchronized public java.sql.Statement createStatement(
1513: int resultSetType, int resultSetConcurrency,
1514: int resultSetHoldability) throws SQLException {
1515: try {
1516: if (agent_.loggingEnabled()) {
1517: agent_.logWriter_.traceEntry(this , "createStatement",
1518: resultSetType, resultSetConcurrency,
1519: resultSetHoldability);
1520: }
1521: Statement s = createStatementX(resultSetType,
1522: resultSetConcurrency, resultSetHoldability);
1523: if (agent_.loggingEnabled()) {
1524: agent_.logWriter_.traceExit(this , "createStatement", s);
1525: }
1526: return s;
1527: } catch (SqlException se) {
1528: throw se.getSQLException();
1529: }
1530: }
1531:
1532: private Statement createStatementX(int resultSetType,
1533: int resultSetConcurrency, int resultSetHoldability)
1534: throws SqlException {
1535: checkForClosedConnection();
1536: resultSetType = downgradeResultSetType(resultSetType);
1537: // In an XA global transaction do not allow the
1538: // holdability to be set to hold cursors across
1539: // commits, as the engine does not support it.
1540: // Downgrade the holdability to CLOSE_CURSORS_AT_COMMIT
1541: // and attach a warning. This is specified in
1542: // JDBC 4.0 (proposed final draft) section 16.1.3.1
1543: // Similar code is not needed for PreparedStatement
1544: // as the holdability gets pushed all the way to the
1545: // engine and handled there.
1546: if (this .isXAConnection_ && this .xaState_ == XA_T1_ASSOCIATED) {
1547: if (resultSetHoldability == JDBC30Translation.HOLD_CURSORS_OVER_COMMIT) {
1548: resultSetHoldability = JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
1549: accumulateWarning(new SqlWarning(
1550: agent_.logWriter_,
1551: new ClientMessageId(
1552: SQLState.HOLDABLE_RESULT_SET_NOT_AVAILABLE)));
1553: }
1554: }
1555: Statement s = newStatement_(resultSetType,
1556: resultSetConcurrency, resultSetHoldability);
1557: s.cursorAttributesToSendOnPrepare_ = s
1558: .cacheCursorAttributesToSendOnPrepare();
1559: openStatements_.put(s, null);
1560: return s;
1561: }
1562:
1563: // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
1564: // right thing to do here... because if property on the dataSource changes, we may have
1565: // to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
1566: protected void resetStatement(Statement s) throws SqlException {
1567: String cursorAttributesToSendOnPrepare = s.cursorAttributesToSendOnPrepare_;
1568: resetStatement_(s, s.resultSetType_, s.resultSetConcurrency_,
1569: s.resultSetHoldability_);
1570: s.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1571: }
1572:
1573: synchronized public java.sql.PreparedStatement prepareStatement(
1574: String sql, int resultSetType, int resultSetConcurrency,
1575: int resultSetHoldability) throws SQLException {
1576: try {
1577: if (agent_.loggingEnabled()) {
1578: agent_.logWriter_.traceEntry(this , "prepareStatement",
1579: sql, resultSetType, resultSetConcurrency,
1580: resultSetHoldability);
1581: }
1582: PreparedStatement ps = prepareStatementX(sql,
1583: resultSetType, resultSetConcurrency,
1584: resultSetHoldability,
1585: java.sql.Statement.NO_GENERATED_KEYS, null);
1586: if (agent_.loggingEnabled()) {
1587: agent_.logWriter_.traceExit(this , "prepareStatement",
1588: ps);
1589: }
1590: return ps;
1591: } catch (SqlException se) {
1592: throw se.getSQLException();
1593: }
1594: }
1595:
1596: // used by DBMD
1597: PreparedStatement prepareStatementX(String sql, int resultSetType,
1598: int resultSetConcurrency, int resultSetHoldability,
1599: int autoGeneratedKeys, String[] columnNames)
1600: throws SqlException {
1601: checkForClosedConnection();
1602: checkAutoGeneratedKeysParameters(autoGeneratedKeys, columnNames);
1603: resultSetType = downgradeResultSetType(resultSetType);
1604: PreparedStatement ps = newPreparedStatement_(sql,
1605: resultSetType, resultSetConcurrency,
1606: resultSetHoldability, autoGeneratedKeys, columnNames);
1607: ps.cursorAttributesToSendOnPrepare_ = ps
1608: .cacheCursorAttributesToSendOnPrepare();
1609: ps.prepare();
1610: openStatements_.put(ps, null);
1611: return ps;
1612: }
1613:
1614: // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
1615: // right thing to do here... because if property on the dataSource changes, we may have
1616: // to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
1617: protected void resetPrepareStatement(PreparedStatement ps)
1618: throws SqlException {
1619: String cursorAttributesToSendOnPrepare = ps.cursorAttributesToSendOnPrepare_;
1620: resetPreparedStatement_(ps, ps.sql_, ps.resultSetType_,
1621: ps.resultSetConcurrency_, ps.resultSetHoldability_,
1622: ps.autoGeneratedKeys_, ps.generatedKeysColumnNames_);
1623: ps.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1624: ps.prepare();
1625: }
1626:
1627: synchronized public java.sql.CallableStatement prepareCall(
1628: String sql, int resultSetType, int resultSetConcurrency,
1629: int resultSetHoldability) throws SQLException {
1630: try {
1631: if (agent_.loggingEnabled()) {
1632: agent_.logWriter_.traceEntry(this , "prepareCall", sql,
1633: resultSetType, resultSetConcurrency,
1634: resultSetHoldability);
1635: }
1636: CallableStatement cs = prepareCallX(sql, resultSetType,
1637: resultSetConcurrency, resultSetHoldability);
1638: if (agent_.loggingEnabled()) {
1639: agent_.logWriter_.traceExit(this , "prepareCall", cs);
1640: }
1641: return cs;
1642: } catch (SqlException se) {
1643: throw se.getSQLException();
1644: }
1645: }
1646:
1647: private CallableStatement prepareCallX(String sql,
1648: int resultSetType, int resultSetConcurrency,
1649: int resultSetHoldability) throws SqlException {
1650: checkForClosedConnection();
1651: resultSetType = downgradeResultSetType(resultSetType);
1652: CallableStatement cs = newCallableStatement_(sql,
1653: resultSetType, resultSetConcurrency,
1654: resultSetHoldability);
1655: cs.cursorAttributesToSendOnPrepare_ = cs
1656: .cacheCursorAttributesToSendOnPrepare();
1657: cs.prepare();
1658: openStatements_.put(cs, null);
1659: return cs;
1660: }
1661:
1662: protected void resetPrepareCall(CallableStatement cs)
1663: throws SqlException {
1664: String cursorAttributesToSendOnPrepare = cs.cursorAttributesToSendOnPrepare_;
1665: resetCallableStatement_(cs, cs.sql_, cs.resultSetType_,
1666: cs.resultSetConcurrency_, cs.resultSetHoldability_);
1667: cs.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
1668: cs.prepare();
1669: }
1670:
1671: public java.sql.PreparedStatement prepareStatement(String sql,
1672: int autoGeneratedKeys) throws SQLException {
1673: try {
1674: if (agent_.loggingEnabled()) {
1675: agent_.logWriter_.traceEntry(this , "prepareStatement",
1676: sql, autoGeneratedKeys);
1677: }
1678: PreparedStatement ps = prepareStatementX(sql,
1679: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1680: java.sql.ResultSet.CONCUR_READ_ONLY, holdability(),
1681: autoGeneratedKeys, null);
1682: if (agent_.loggingEnabled()) {
1683: agent_.logWriter_.traceExit(this , "prepareStatement",
1684: ps);
1685: }
1686: return ps;
1687: } catch (SqlException se) {
1688: throw se.getSQLException();
1689: }
1690: }
1691:
1692: public java.sql.PreparedStatement prepareStatement(String sql,
1693: int columnIndexes[]) throws SQLException {
1694: try {
1695: if (agent_.loggingEnabled()) {
1696: agent_.logWriter_.traceEntry(this , "prepareStatement",
1697: sql, columnIndexes);
1698: }
1699: checkForClosedConnection();
1700: throw new SqlException(agent_.logWriter_,
1701: new ClientMessageId(SQLState.NOT_IMPLEMENTED),
1702: "prepareStatement(String, int[])");
1703: } catch (SqlException se) {
1704: throw se.getSQLException();
1705: }
1706: }
1707:
1708: public java.sql.PreparedStatement prepareStatement(String sql,
1709: String columnNames[]) throws SQLException {
1710: try {
1711: if (agent_.loggingEnabled()) {
1712: agent_.logWriter_.traceEntry(this , "prepareStatement",
1713: sql, columnNames);
1714: }
1715: PreparedStatement ps = prepareStatementX(sql,
1716: java.sql.ResultSet.TYPE_FORWARD_ONLY,
1717: java.sql.ResultSet.CONCUR_READ_ONLY, holdability(),
1718: java.sql.Statement.RETURN_GENERATED_KEYS,
1719: columnNames);
1720: if (agent_.loggingEnabled()) {
1721: agent_.logWriter_.traceExit(this , "prepareStatement",
1722: ps);
1723: }
1724: return ps;
1725: } catch (SqlException se) {
1726: throw se.getSQLException();
1727: }
1728: }
1729:
1730: // ---------------------------------------------------------------------------
1731:
1732: protected abstract boolean allowCloseInUOW_();
1733:
1734: protected abstract boolean doCloseStatementsOnClose_();
1735:
1736: public abstract SectionManager newSectionManager(String collection,
1737: Agent agent, String databaseName);
1738:
1739: //--------------------Abstract material factory methods-----------------
1740:
1741: protected abstract Agent newAgent_(LogWriter logWriter,
1742: int loginTimeout, String serverName, int portNumber)
1743: throws SqlException;
1744:
1745: protected abstract DatabaseMetaData newDatabaseMetaData_();
1746:
1747: protected abstract Statement newStatement_(int type,
1748: int concurrency, int holdability) throws SqlException;
1749:
1750: protected abstract void resetStatement_(Statement statement,
1751: int type, int concurrency, int holdability)
1752: throws SqlException;
1753:
1754: protected abstract PreparedStatement newPositionedUpdatePreparedStatement_(
1755: String sql, Section section) throws SqlException;
1756:
1757: protected abstract PreparedStatement newPreparedStatement_(
1758: String sql, int type, int concurrency, int holdability,
1759: int autoGeneratedKeys, String[] columnNames)
1760: throws SqlException;
1761:
1762: protected abstract void resetPreparedStatement_(
1763: PreparedStatement ps, String sql, int resultSetType,
1764: int resultSetConcurrency, int resultSetHoldability,
1765: int autoGeneratedKeys, String[] columnNames)
1766: throws SqlException;
1767:
1768: protected abstract CallableStatement newCallableStatement_(
1769: String sql, int type, int concurrency, int holdability)
1770: throws SqlException;
1771:
1772: protected abstract void resetCallableStatement_(
1773: CallableStatement cs, String sql, int resultSetType,
1774: int resultSetConcurrency, int resultSetHoldability)
1775: throws SqlException;
1776:
1777: // ----------------------- abstract box car and callback methods ---------------------
1778: // All callbacks must be client-side only operations.
1779:
1780: public void completeConnect() throws SqlException {
1781: open_ = true;
1782: databaseMetaData_ = newDatabaseMetaData_();
1783:
1784: agent_.sectionManager_ = newSectionManager("NULLID", agent_,
1785: databaseName_);
1786: if (agent_.loggingEnabled()) {
1787: agent_.logWriter_.traceConnectExit(this );
1788: }
1789: }
1790:
1791: public abstract void writeCommitSubstitute_() throws SqlException;
1792:
1793: public abstract void readCommitSubstitute_() throws SqlException;
1794:
1795: public abstract void writeLocalXAStart_() throws SqlException;
1796:
1797: public abstract void readLocalXAStart_() throws SqlException;
1798:
1799: public abstract void writeLocalXACommit_() throws SqlException;
1800:
1801: protected abstract void writeXACommit_() throws SqlException;
1802:
1803: public abstract void readLocalXACommit_() throws SqlException;
1804:
1805: protected abstract void readXACommit_() throws SqlException;
1806:
1807: public abstract void writeLocalCommit_() throws SqlException;
1808:
1809: public abstract void readLocalCommit_() throws SqlException;
1810:
1811: protected abstract void writeXATransactionStart(Statement statement)
1812: throws SqlException;
1813:
1814: public void completeLocalCommit() {
1815: java.util.Set keySet = CommitAndRollbackListeners_.keySet();
1816: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
1817: UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1818: listener.completeLocalCommit(i);
1819: }
1820: inUnitOfWork_ = false;
1821: }
1822:
1823: public abstract void writeLocalRollback_() throws SqlException;
1824:
1825: public abstract void readLocalRollback_() throws SqlException;
1826:
1827: // A callback for certain non-fatal exceptions that occur when parsing error replies.
1828: // This is a client-side only operation.
1829: // This method will only throw an exception on bug check.
1830: public void completeLocalRollback() {
1831: java.util.Set keySet = CommitAndRollbackListeners_.keySet();
1832: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
1833: UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1834: listener.completeLocalRollback(i);
1835: }
1836: inUnitOfWork_ = false;
1837: }
1838:
1839: /**
1840: *
1841: * Rollback the specific UnitOfWorkListener.
1842: * @param uwl The UnitOfWorkLitener to be rolled back
1843: *
1844: */
1845: public void completeSpecificRollback(UnitOfWorkListener uwl) {
1846: java.util.Set keySet = CommitAndRollbackListeners_.keySet();
1847: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
1848: UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
1849: if (listener == uwl) {
1850: listener.completeLocalRollback(i);
1851: break;
1852: }
1853: }
1854: inUnitOfWork_ = false;
1855: }
1856:
1857: public abstract void writeLocalXARollback_() throws SqlException;
1858:
1859: protected abstract void writeXARollback_() throws SqlException;
1860:
1861: public abstract void readLocalXARollback_() throws SqlException;
1862:
1863: protected abstract void readXARollback_() throws SqlException;
1864:
1865: public void writeTransactionStart(Statement statement)
1866: throws SqlException {
1867: if (isXAConnection_) {
1868: writeXATransactionStart(statement);
1869: }
1870: }
1871:
1872: public void readTransactionStart() throws SqlException {
1873: completeTransactionStart();
1874: }
1875:
1876: void completeTransactionStart() {
1877: inUnitOfWork_ = true;
1878: }
1879:
1880: // Occurs autonomously
1881: public void completeAbnormalUnitOfWork() {
1882: completeLocalRollback();
1883: }
1884:
1885: /**
1886: *
1887: * Rollback the UnitOfWorkListener specifically.
1888: * @param uwl The UnitOfWorkListener to be rolled back.
1889: *
1890: */
1891: public void completeAbnormalUnitOfWork(UnitOfWorkListener uwl) {
1892: completeSpecificRollback(uwl);
1893: }
1894:
1895: // Called by Connection.close(), NetConnection.errorRollbackDisconnect().
1896: // The Agent's client-side resources associated with database connection are reclaimed (eg. socket).
1897: // And this connection and all associated statements and result sets are marked closed.
1898: // This is a client-side only operation.
1899: // This method will only throw an exception if the agent cannot be closed.
1900: public void completeChainBreakingDisconnect() {
1901: open_ = false;
1902: completeLocalRollback();
1903: markStatementsClosed();
1904: }
1905:
1906: public void completeSqlca(Sqlca sqlca) {
1907: if (sqlca == null) {
1908: } else if (sqlca.getSqlCode() > 0) {
1909: accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca));
1910: } else if (sqlca.getSqlCode() < 0) {
1911: agent_.accumulateReadException(new SqlException(
1912: agent_.logWriter_, sqlca));
1913: }
1914: }
1915:
1916: public abstract void addSpecialRegisters(String s);
1917:
1918: // can this only be called by the PooledConnection
1919: // can this be called on a closed connection
1920: // can this be called in a unit of work
1921: // can this be called from within a stored procedure
1922: //
1923: synchronized public void reset(LogWriter logWriter, String user,
1924: String password, ClientBaseDataSource ds,
1925: boolean recomputeFromDataSource) throws SqlException {
1926: if (logWriter != null) {
1927: logWriter.traceConnectResetEntry(this , logWriter, user,
1928: (ds != null) ? ds : dataSource_);
1929: }
1930: try {
1931: reset_(logWriter, user, password, ds,
1932: recomputeFromDataSource);
1933: } catch (SqlException sqle) {
1934: DisconnectException de = new DisconnectException(agent_,
1935: new ClientMessageId(
1936: SQLState.CONNECTION_FAILED_ON_RESET));
1937: de.setNextException(sqle);
1938: throw de;
1939: }
1940: }
1941:
1942: synchronized public void reset(LogWriter logWriter,
1943: ClientBaseDataSource ds, boolean recomputeFromDataSource)
1944: throws SqlException {
1945: if (logWriter != null) {
1946: logWriter.traceConnectResetEntry(this , logWriter, null,
1947: (ds != null) ? ds : dataSource_);
1948: }
1949: try {
1950: reset_(logWriter, ds, recomputeFromDataSource);
1951: } catch (SqlException sqle) {
1952: DisconnectException de = new DisconnectException(agent_,
1953: new ClientMessageId(
1954: SQLState.CONNECTION_FAILED_ON_RESET));
1955: de.setNextException(sqle);
1956: throw de;
1957: }
1958: }
1959:
1960: synchronized public void lightReset() throws SqlException {
1961: if (!open_ && !availableForReuse_) {
1962: return;
1963: }
1964: open_ = true;
1965: availableForReuse_ = false;
1966: }
1967:
1968: abstract protected void reset_(LogWriter logWriter, String user,
1969: String password, ClientBaseDataSource ds,
1970: boolean recomputerFromDataSource) throws SqlException;
1971:
1972: abstract protected void reset_(LogWriter logWriter,
1973: ClientBaseDataSource ds, boolean recomputerFromDataSource)
1974: throws SqlException;
1975:
1976: protected void completeReset(boolean isDeferredReset,
1977: boolean recomputeFromDataSource) throws SqlException {
1978: open_ = true;
1979:
1980: completeLocalRollback(); // this will close the cursors if the physical connection hadn't been closed for reuse properly
1981:
1982: // Reopen physical statement resources associated with previous uses of this physical connection.
1983: // Notice that these physical statements may not belong to this logical connection.
1984: // Iterate through the physical statements and re-enable them for reuse.
1985:
1986: java.util.Set keySet = openStatements_.keySet();
1987: for (java.util.Iterator i = keySet.iterator(); i.hasNext();) {
1988: Object o = i.next();
1989: ((Statement) o).reset(recomputeFromDataSource);
1990:
1991: }
1992:
1993: if (!isDeferredReset && agent_.loggingEnabled()) {
1994: agent_.logWriter_.traceConnectResetExit(this );
1995: }
1996: }
1997:
1998: //-------------------------------helper methods-------------------------------
1999:
2000: protected void checkForClosedConnection() throws SqlException {
2001: if (!open_) {
2002: agent_.checkForDeferredExceptions();
2003: throw new SqlException(agent_.logWriter_,
2004: new ClientMessageId(SQLState.NO_CURRENT_CONNECTION));
2005: } else {
2006: agent_.checkForDeferredExceptions();
2007: }
2008: }
2009:
2010: void checkAutoGeneratedKeysParameters(int autoGeneratedKeys,
2011: String[] columnNames) throws SqlException {
2012: if (autoGeneratedKeys != java.sql.Statement.NO_GENERATED_KEYS
2013: && autoGeneratedKeys != java.sql.Statement.RETURN_GENERATED_KEYS) {
2014: throw new SqlException(
2015: agent_.logWriter_,
2016: new ClientMessageId(SQLState.BAD_AUTO_GEN_KEY_VALUE),
2017: new Integer(autoGeneratedKeys));
2018: }
2019:
2020: if (columnNames != null) {
2021: throw new SqlException(agent_.logWriter_,
2022: new ClientMessageId(SQLState.NOT_IMPLEMENTED),
2023: "getAutoGeneratedKeys(columnNames == null)");
2024: }
2025:
2026: }
2027:
2028: public boolean isXAConnection() {
2029: return isXAConnection_;
2030: }
2031:
2032: public int getXAState() {
2033: return xaState_;
2034: }
2035:
2036: public void setXAState(int state) {
2037: xaState_ = state;
2038: }
2039:
2040: public void accumulateWarning(SqlWarning e) {
2041: if (warnings_ == null) {
2042: warnings_ = e;
2043: } else {
2044: warnings_.setNextException(e);
2045: }
2046: }
2047:
2048: public void accumulate440WarningForMessageProcFailure(SqlWarning e) {
2049: if (!accumulated440ForMessageProcFailure_) {
2050: accumulateWarning(e);
2051: accumulated440ForMessageProcFailure_ = true;
2052: }
2053: }
2054:
2055: public void accumulate444WarningForMessageProcFailure(SqlWarning e) {
2056: if (!accumulated444ForMessageProcFailure_) {
2057: accumulateWarning(e);
2058: accumulated444ForMessageProcFailure_ = true;
2059: }
2060: }
2061:
2062: // get the server version
2063: public int getServerVersion() {
2064: return databaseMetaData_.productLevel_.versionLevel_;
2065: }
2066:
2067: public void setInUnitOfWork(boolean inUnitOfWork) {
2068: inUnitOfWork_ = inUnitOfWork;
2069: }
2070:
2071: /**
2072: * Return the holdabilty for the Connection. Matches the
2073: * embedded driver in the restriction that while in a
2074: * global (XA) transaction the holdability is CLOSE_CURSORS_AT_COMMIT.
2075: * Otherwise return the holdability set by the user.
2076: */
2077: final int holdability() {
2078: if (this.isXAConnection_ && this.xaState_ == XA_T1_ASSOCIATED)
2079: return JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
2080: return holdability;
2081: }
2082:
2083: }
|