You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by jb...@apache.org on 2005/05/02 08:26:03 UTC
svn commit: r165585 [7/42] - in
/incubator/derby/code/trunk/java/client/org/apache/derby: client/
client/am/ client/net/ client/resources/ jdbc/
Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?rev=165585&r1=165584&r2=165585&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Sun May 1 23:25:59 2005
@@ -21,1523 +21,1639 @@
package org.apache.derby.client.am;
import org.apache.derby.jdbc.ClientDataSource;
-import org.apache.derby.client.am.Section;
public abstract class Connection implements java.sql.Connection,
- ConnectionCallbackInterface
-{
- //---------------------navigational members-----------------------------------
-
-
- public Agent agent_;
-
- public DatabaseMetaData databaseMetaData_;
- // Since DERBY prepared statements must be re-prepared after a commit,
- // then we must traverse this list after a commit and notify statements
- // that they are now in an un-prepared state.
- final java.util.LinkedList openStatements_ = new java.util.LinkedList();
-
- // Some statuses of DERBY objects may be invalid on server either after only rollback
- // or after both commit and rollback. For example,
- // (1) prepared statements need to be re-prepared
- // after both commit and rollback
- // (2) result set will be unpositioned on server after both commit and rollback.
- // If they only depend on rollback, they need to get on RollbackOnlyListeners_.
- // If they depend on both commit and rollback, they need to get on CommitAndRollbackListeners_.
- final java.util.LinkedList RollbackOnlyListeners_ = new java.util.LinkedList();
- final java.util.LinkedList CommitAndRollbackListeners_ = new java.util.LinkedList();
- private SqlWarning warnings_ = null;
-
- // ------------------------properties set for life of connection--------------
-
- // See ClientDataSource pre-connect settings
- public transient String user_;
- public boolean retrieveMessageText_;
- protected boolean jdbcReadOnly_;
- public int resultSetHoldability_;
- public String databaseName_;
-
- // Holds the Product-Specific Identifier which specifies
- // the product release level of a DDM Server.
- // The max length is 8.
- public String productID_;
-
- // Used to get the public key and encrypt password and/or userid
- protected EncryptionManager encryptionManager_;
-
- // used to set transaction isolation level
- private Statement setTransactionIsolationStmt = null;
- // ------------------------dynamic properties---------------------------------
-
- protected boolean open_ = true;
- protected boolean availableForReuse_ = false;
-
- public int isolation_ = Configuration.defaultIsolation;
- public boolean autoCommit_ = true;
- protected boolean inUnitOfWork_ = false; // This means a transaction is in progress.
-
- private boolean accumulated440ForMessageProcFailure_ = false;
- private boolean accumulated444ForMessageProcFailure_ = false;
- private boolean accumulatedSetReadOnlyWarning_ = false;
-
-
-
- //---------------------XA-----------------------------------------------------
-
- protected boolean isXAConnection_ = false; // Indicates an XA connection
-
- // XA States
- public static final int XA_OPEN_IDLE = 0;
- public static final int XA_LOCAL = 1; // local transaction started by DNC
- public static final int XA_LOCAL_CCC = 2; // local transaction started by CCC
- public static final int XA_ACTIVE = 3;
- public static final int XA_ENDED = 4;
- public static final int XA_HEUR_COMP = 5;
- public static final int XA_SUSPENDED = 6;
- public static final int XA_PREPARED = 7;
- public static final int XA_ROLLBACK = 8;
- public static final int XA_LOCAL_START_SENT = 9;
- public static final int XA_UNKNOWN = 10;
- public static final int XA_GLOBAL_START_SENT = 11;
- public static final int XA_PENDING_END = 12;
- public static final int XA_RBATHER = 13;
- public static final int XA_RECOVER = 14;
- public static final int XA_EMPTY_TRANSACTION = 15;
- public static final int XA_RBROLLBACK = 16;
- public static final int XA_PENDING_START = 17;
- public static final int XA_EMPTY_SUSPENDED = 18;
-
-
- protected int xaState_ = XA_OPEN_IDLE;
-
- // XA Host Type
- public int xaHostVersion_ = 0;
-
- public int loginTimeout_;
- public org.apache.derby.jdbc.ClientDataSource dataSource_;
- public String serverNameIP_;
- public int portNumber_;
-
- public java.util.Hashtable clientCursorNameCache_ = new java.util.Hashtable();
- public boolean canUseCachedConnectBytes_ = false;
- public int commBufferSize_ = 32767;
-
- // indicates if a deferred reset connection is required
- public boolean resetConnectionAtFirstSql_ = false;
-
- //---------------------constructors/finalizer---------------------------------
-
- // For jdbc 2 connections
- protected Connection (org.apache.derby.client.am.LogWriter logWriter,
- String user,
- String password,
- org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException
- {
- initConnection(logWriter, user, dataSource);
- }
-
- protected Connection (org.apache.derby.client.am.LogWriter logWriter,
- String user,
- String password,
- boolean isXAConn,
- org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException
- {
- isXAConnection_ = isXAConn;
- initConnection(logWriter, user, dataSource);
- }
-
- // For jdbc 2 connections
- protected void initConnection (org.apache.derby.client.am.LogWriter logWriter,
- String user,
- org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException
- {
- if (logWriter != null) logWriter.traceConnectEntry (dataSource);
- org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration (logWriter);
-
- user_ = user;
-
- // Extract common properties.
- databaseName_ = dataSource.getDatabaseName() + dataSource.getConnectionAttributes();
- retrieveMessageText_ = dataSource.getRetrieveMessageText();
-
- loginTimeout_ = dataSource.getLoginTimeout();
- dataSource_ = dataSource;
-
- serverNameIP_ = dataSource.getServerName();
- portNumber_ = dataSource.getPortNumber();
-
-
- agent_ = newAgent_ (logWriter,
- loginTimeout_,
- serverNameIP_,
- portNumber_);
- }
-
- // For jdbc 2 connections
- protected Connection (org.apache.derby.client.am.LogWriter logWriter,
- boolean isXAConn,
- org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException
- {
- if (logWriter != null) logWriter.traceConnectEntry (dataSource);
- isXAConnection_ = isXAConn;
- org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration (logWriter);
-
- user_ = ClientDataSource.propertyDefault_user;
-
- // Extract common properties.
- databaseName_ = dataSource.getDatabaseName();
- retrieveMessageText_ = dataSource.getRetrieveMessageText();
-
- loginTimeout_= dataSource.getLoginTimeout();
- dataSource_ = dataSource;
-
- serverNameIP_ = dataSource.getServerName();
- portNumber_ = dataSource.getPortNumber();
-
-
- agent_ = newAgent_ (logWriter,
- loginTimeout_,
- serverNameIP_,
- portNumber_);
- }
+ ConnectionCallbackInterface {
+ //---------------------navigational members-----------------------------------
- // This is a callback method, called by subsystem - NetConnection
- protected void resetConnection (LogWriter logWriter,
- String user,
- ClientDataSource ds,
- boolean recomputeFromDataSource) throws SqlException
- {
- // clearWarningsX() will re-initialize the following properties
- clearWarningsX();
-
- user_ = (user != null) ? user : user_;
-
- if (ds != null && recomputeFromDataSource) { // no need to reinitialize connection state if ds hasn't changed
- user_ = (user != null) ? user : ds.getUser();;
- retrieveMessageText_ = ds.getRetrieveMessageText();
+ public Agent agent_;
+ public DatabaseMetaData databaseMetaData_;
+ // Since DERBY prepared statements must be re-prepared after a commit,
+ // then we must traverse this list after a commit and notify statements
+ // that they are now in an un-prepared state.
+ final java.util.LinkedList openStatements_ = new java.util.LinkedList();
+
+ // Some statuses of DERBY objects may be invalid on server either after only rollback
+ // or after both commit and rollback. For example,
+ // (1) prepared statements need to be re-prepared
+ // after both commit and rollback
+ // (2) result set will be unpositioned on server after both commit and rollback.
+ // If they only depend on rollback, they need to get on RollbackOnlyListeners_.
+ // If they depend on both commit and rollback, they need to get on CommitAndRollbackListeners_.
+ final java.util.LinkedList RollbackOnlyListeners_ = new java.util.LinkedList();
+ final java.util.LinkedList CommitAndRollbackListeners_ = new java.util.LinkedList();
+ private SqlWarning warnings_ = null;
+
+ // ------------------------properties set for life of connection--------------
+
+ // See ClientDataSource pre-connect settings
+ public transient String user_;
+ public boolean retrieveMessageText_;
+ protected boolean jdbcReadOnly_;
+ public int resultSetHoldability_;
+ public String databaseName_;
+
+ // Holds the Product-Specific Identifier which specifies
+ // the product release level of a DDM Server.
+ // The max length is 8.
+ public String productID_;
+
+ // Used to get the public key and encrypt password and/or userid
+ protected EncryptionManager encryptionManager_;
+
+ // used to set transaction isolation level
+ private Statement setTransactionIsolationStmt = null;
+ // ------------------------dynamic properties---------------------------------
+
+ protected boolean open_ = true;
+ protected boolean availableForReuse_ = false;
+
+ public int isolation_ = Configuration.defaultIsolation;
+ public boolean autoCommit_ = true;
+ protected boolean inUnitOfWork_ = false; // This means a transaction is in progress.
+
+ private boolean accumulated440ForMessageProcFailure_ = false;
+ private boolean accumulated444ForMessageProcFailure_ = false;
+ private boolean accumulatedSetReadOnlyWarning_ = false;
+
+
+
+ //---------------------XA-----------------------------------------------------
+
+ protected boolean isXAConnection_ = false; // Indicates an XA connection
+
+ // XA States
+ public static final int XA_OPEN_IDLE = 0;
+ public static final int XA_LOCAL = 1; // local transaction started by DNC
+ public static final int XA_LOCAL_CCC = 2; // local transaction started by CCC
+ public static final int XA_ACTIVE = 3;
+ public static final int XA_ENDED = 4;
+ public static final int XA_HEUR_COMP = 5;
+ public static final int XA_SUSPENDED = 6;
+ public static final int XA_PREPARED = 7;
+ public static final int XA_ROLLBACK = 8;
+ public static final int XA_LOCAL_START_SENT = 9;
+ public static final int XA_UNKNOWN = 10;
+ public static final int XA_GLOBAL_START_SENT = 11;
+ public static final int XA_PENDING_END = 12;
+ public static final int XA_RBATHER = 13;
+ public static final int XA_RECOVER = 14;
+ public static final int XA_EMPTY_TRANSACTION = 15;
+ public static final int XA_RBROLLBACK = 16;
+ public static final int XA_PENDING_START = 17;
+ public static final int XA_EMPTY_SUSPENDED = 18;
+
+
+ protected int xaState_ = XA_OPEN_IDLE;
+
+ // XA Host Type
+ public int xaHostVersion_ = 0;
+
+ public int loginTimeout_;
+ public org.apache.derby.jdbc.ClientDataSource dataSource_;
+ public String serverNameIP_;
+ public int portNumber_;
+
+ public java.util.Hashtable clientCursorNameCache_ = new java.util.Hashtable();
+ public boolean canUseCachedConnectBytes_ = false;
+ public int commBufferSize_ = 32767;
+
+ // indicates if a deferred reset connection is required
+ public boolean resetConnectionAtFirstSql_ = false;
+
+ //---------------------constructors/finalizer---------------------------------
+
+ // For jdbc 2 connections
+ protected Connection(org.apache.derby.client.am.LogWriter logWriter,
+ String user,
+ String password,
+ org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException {
+ initConnection(logWriter, user, dataSource);
+ }
+
+ protected Connection(org.apache.derby.client.am.LogWriter logWriter,
+ String user,
+ String password,
+ boolean isXAConn,
+ org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException {
+ isXAConnection_ = isXAConn;
+ initConnection(logWriter, user, dataSource);
+ }
- // property encryptionManager_
- // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
- encryptionManager_ = null;
-
- // property: open_
- // this should already be true
+ // For jdbc 2 connections
+ protected void initConnection(org.apache.derby.client.am.LogWriter logWriter,
+ String user,
+ org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException {
+ if (logWriter != null) {
+ logWriter.traceConnectEntry(dataSource);
+ }
+ org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration(logWriter);
+
+ user_ = user;
+
+ // Extract common properties.
+ databaseName_ = dataSource.getDatabaseName() + dataSource.getConnectionAttributes();
+ retrieveMessageText_ = dataSource.getRetrieveMessageText();
+
+ loginTimeout_ = dataSource.getLoginTimeout();
+ dataSource_ = dataSource;
+
+ serverNameIP_ = dataSource.getServerName();
+ portNumber_ = dataSource.getPortNumber();
+
+
+ agent_ = newAgent_(logWriter,
+ loginTimeout_,
+ serverNameIP_,
+ portNumber_);
+ }
+
+ // For jdbc 2 connections
+ protected Connection(org.apache.derby.client.am.LogWriter logWriter,
+ boolean isXAConn,
+ org.apache.derby.jdbc.ClientDataSource dataSource) throws SqlException {
+ if (logWriter != null) {
+ logWriter.traceConnectEntry(dataSource);
+ }
+ isXAConnection_ = isXAConn;
+ org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration(logWriter);
+
+ user_ = ClientDataSource.propertyDefault_user;
+
+ // Extract common properties.
+ databaseName_ = dataSource.getDatabaseName();
+ retrieveMessageText_ = dataSource.getRetrieveMessageText();
+
+ loginTimeout_ = dataSource.getLoginTimeout();
+ dataSource_ = dataSource;
+
+ serverNameIP_ = dataSource.getServerName();
+ portNumber_ = dataSource.getPortNumber();
+
+
+ agent_ = newAgent_(logWriter,
+ loginTimeout_,
+ serverNameIP_,
+ portNumber_);
+ }
+
+ // This is a callback method, called by subsystem - NetConnection
+ protected void resetConnection(LogWriter logWriter,
+ String user,
+ ClientDataSource ds,
+ boolean recomputeFromDataSource) throws SqlException {
+ // clearWarningsX() will re-initialize the following properties
+ clearWarningsX();
+
+ user_ = (user != null) ? user : user_;
+
+ if (ds != null && recomputeFromDataSource) { // no need to reinitialize connection state if ds hasn't changed
+ user_ = (user != null) ? user : ds.getUser();
+ ;
+
+ retrieveMessageText_ = ds.getRetrieveMessageText();
+
+
+ // property encryptionManager_
+ // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
+ encryptionManager_ = null;
+
+ // property: open_
+ // this should already be true
+
+ isolation_ = Configuration.defaultIsolation;
+ autoCommit_ = true;
+ inUnitOfWork_ = false;
+
+ loginTimeout_ = ds.getLoginTimeout();
+ dataSource_ = ds;
+ }
+
+ // property isXAConnection_
+ // leave set to current value. this will impact which connect reset flows are used.
+
+ xaState_ = XA_OPEN_IDLE;
+ if (recomputeFromDataSource) {
+ this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
+ }
+ }
+
+ protected void resetConnection(LogWriter logWriter,
+ String databaseName,
+ java.util.Properties properties) throws SqlException {
+ // clearWarningsX() will re-initialize the following properties
+ // warnings_, accumulated440ForMessageProcFailure_,
+ // accumulated444ForMessageProcFailure_, and accumulatedSetReadOnlyWarning_
+ clearWarningsX();
+
+ databaseName_ = databaseName;
+ user_ = ClientDataSource.getUser(properties);
+
+ retrieveMessageText_ = ClientDataSource.getRetrieveMessageText(properties);
+
+
+ // property encryptionManager_
+ // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
+ encryptionManager_ = null;
+
+ // property: open_
+ // this should already be true
+
+ isolation_ = Configuration.defaultIsolation;
+ autoCommit_ = true;
+ inUnitOfWork_ = false;
+
+ // property isXAConnection_
+ // leave set to current value. this will impact which connect reset flows are used.
+
+ xaState_ = XA_OPEN_IDLE;
+
+ this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
+
+ }
+
+
+ // For jdbc 1 connections
+ protected Connection(LogWriter logWriter,
+ int driverManagerLoginTimeout,
+ String serverName,
+ int portNumber,
+ String databaseName,
+ java.util.Properties properties) throws SqlException {
+ if (logWriter != null) {
+ logWriter.traceConnectEntry(serverName, portNumber, databaseName, properties);
+ }
+ org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration(logWriter);
+
+ databaseName_ = databaseName;
+
+ // Extract common properties.
+ user_ = ClientDataSource.getUser(properties);
+ retrieveMessageText_ = ClientDataSource.getRetrieveMessageText(properties);
+
+ loginTimeout_ = driverManagerLoginTimeout;
+ serverNameIP_ = serverName;
+ portNumber_ = portNumber;
+
+ agent_ = newAgent_(logWriter,
+ loginTimeout_,
+ serverNameIP_,
+ portNumber_);
+ }
+
+ // Users are advised to call the method close() on Statement and Connection objects when they are done with them.
+ // However, some users will forget, and some code may get killed before it can close these objects.
+ // Therefore, if JDBC drivers have state associated with JDBC objects that need to get
+ // explicitly cleared up, they should provide finalize methods to take care of them.
+ // The garbage collector will call these finalize methods when the objects are found to be garbage,
+ // and this will give the driver a chance to close (or otherwise clean up) the objects.
+ // Note, however, that there is no guarantee that the garbage collector will ever run.
+ // If that is the case, the finalizers will not be called.
+ protected void finalize() throws java.lang.Throwable {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "finalize");
+ }
+
+ // finalize() differs from close() in that it will not throw an
+ // exception if a transaction is in progress.
+ // finalize() also differs from close() in that it will not drive
+ // an auto-commit before disconnecting.
+ //
+ // If a transaction is in progress, a close() request will throw an SqlException.
+ // However, if a connection with an incomplete transaction is finalized,
+ // or is abruptly terminated by application exit,
+ // the normal rollback semantics imposed by the DERBY server are adopted.
+ // So we just pull the plug and let the server handle this default semantic.
+
+ if (!open_) {
+ return;
+ }
+ agent_.disconnectEvent();
+ super.finalize();
+ }
+
+ // ---------------------------jdbc 1------------------------------------------
+
+ synchronized public java.sql.Statement createStatement() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "createStatement");
+ }
+ Statement s = createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "createStatement", s);
+ }
+ return s;
+ }
+
+ synchronized public java.sql.PreparedStatement prepareStatement(String sql) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql);
+ }
+ PreparedStatement ps = prepareStatementX(sql,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_,
+ java.sql.Statement.NO_GENERATED_KEYS,
+ null);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareStatement", ps);
+ }
+ return ps;
+ }
+
+ // For internal use only. Use by updatable result set code.
+ synchronized public PreparedStatement preparePositionedUpdateStatement(String sql, Section querySection) throws SqlException {
+ checkForClosedConnection();
+ // create a net material prepared statement.
+ PreparedStatement preparedStatement = newPositionedUpdatePreparedStatement_(sql, querySection);
+ preparedStatement.flowPrepareDescribeInputOutput();
+ // The positioned update statement is not added to the list of open statements,
+ // because this would cause a java.util.ConcurrentModificationException when
+ // iterating thru the list of open statements to call completeRollback().
+ // An updatable result set is marked closed on a call to completeRollback(),
+ // and would therefore need to close the positioned update statement associated with the result set which would cause
+ // it to be removed from the open statements list. Resulting in concurrent modification
+ // on the open statements list.
+ // Notice that ordinary Statement.closeX() is never called on the positioned update statement,
+ // rather markClosed() is called to avoid trying to remove the statement from the openStatements_ list.
+ return preparedStatement;
+ }
+
+ synchronized public java.sql.CallableStatement prepareCall(String sql) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareCall", sql);
+ }
+ CallableStatement cs = prepareCallX(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareCall", cs);
+ }
+ return cs;
+ }
+
+ synchronized PreparedStatement prepareDynamicCatalogQuery(String sql) throws SqlException {
+ PreparedStatement ps = newPreparedStatement_(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_, java.sql.Statement.NO_GENERATED_KEYS, null);
+ ps.isCatalogQuery_ = true;
+ ps.prepare();
+ openStatements_.add(ps);
+ return ps;
+ }
+
+ public String nativeSQL(String sql) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "nativeSQL", sql);
+ }
+ String nativeSql = nativeSQLX(sql);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "nativeSQL", nativeSql);
+ }
+ return nativeSql;
+ }
+
+ synchronized public String nativeSQLX(String sql) throws SqlException {
+ checkForClosedConnection();
+ if (sql == null) {
+ throw new SqlException(agent_.logWriter_, "Null SQL string passed.");
+ }
+
+ // Derby can handle the escape syntax directly so only needs escape
+ // processing for { ? = CALL ....}
+ String trimSql = sql.trim();
+ if (trimSql.startsWith("{")) {
+ if (trimSql.lastIndexOf("}") >= 0) {
+ return trimSql.substring(1, trimSql.lastIndexOf("}"));
+ }
+ }
+
+ return trimSql;
+ }
+
+ // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
+ // primary usage is distinction between local and global trans. envs.;
+ protected abstract boolean disallowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException;
+
+ synchronized public void setAutoCommit(boolean autoCommit) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setAutoCommit", autoCommit);
+ }
+ checkForClosedConnection();
+
+ if (disallowLocalCommitRollback_()) {
+ if (autoCommit) { // can't toggle to autocommit mode when between xars.start() and xars.end()
+ throw new SqlException(agent_.logWriter_,
+ "setAutoCommit(true) invalid during global transaction",
+ SqlState._2D521, // Spec'ed by PROTOCOL
+ SqlCode.invalidSetAutoCommitUnderXA);
+ }
+ } else {
+ if (autoCommit == autoCommit_) {
+ return; // don't flow a commit if nothing changed.
+ }
+ if (inUnitOfWork_) {
+ flowCommit(); // we are not between xars.start() and xars.end(), can flow commit
+ }
+ }
+ autoCommit_ = autoCommit;
+ }
+
+ public boolean getAutoCommit() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getAutoCommit", autoCommit_);
+ }
+ if (disallowLocalCommitRollback_()) { // autoCommit is always false between xars.start() and xars.end()
+ return false;
+ }
+ return autoCommit_;
+ }
+
+ synchronized public void commit() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "commit");
+ }
+
+ // the following XA State check must be in commit instead of commitX since
+ // external application call commit, the SqlException should be thrown
+ // only if an external application calls commit during a Global Transaction,
+ // internal code will call commitX which will ignore the commit request
+ // while in a Global transaction
+ checkForInvalidXAStateOnCommitOrRollback();
+ checkForClosedConnection();
+ flowCommit();
+ }
+
+ private void checkForInvalidXAStateOnCommitOrRollback() throws SqlException {
+ if (disallowLocalCommitRollback_()) {
+ throw new SqlException(agent_.logWriter_,
+ "COMMIT or ROLLBACK invalid for application execution environment",
+ SqlState._2D521, // Spec'ed by PROTOCOL
+ SqlCode.invalidCommitOrRollbackUnderXA);
+ }
+ }
+
+ public void flowCommit() throws SqlException {
+ // Per JDBC specification (see javadoc for Connection.commit()):
+ // "This method should be used only when auto-commit mode has been disabled."
+ // However, some applications do this anyway, it is harmless, so
+ // if they ask to commit, we could go ahead and flow a commit.
+ // But note that rollback() is less harmless, rollback() shouldn't be used in auto-commit mode.
+ // This behavior is subject to further review.
+
+ // if (!this.inUnitOfWork)
+ // return;
+ // We won't try to be "too smart", if the user requests a commit, we'll flow a commit,
+ // regardless of whether or not we're in a unit of work or in auto-commit mode.
+ //
+ if (isXAConnection_) {
+ agent_.beginWriteChainOutsideUOW();
+ writeCommit();
+ agent_.flowOutsideUOW();
+ readCommit(); // This will invoke the commitEvent() callback from the material layer.
+ agent_.endReadChain();
+ } else {
+ agent_.beginWriteChain(null);
+ writeCommit();
+ agent_.flow(null);
+ readCommit(); // This will invoke the commitEvent() callback from the material layer.
+ agent_.endReadChain();
+ }
+
+ }
+
+ // precondition: autoCommit_ is true
+ public void flowAutoCommit() throws SqlException {
+ if (willAutoCommitGenerateFlow()) {
+ flowCommit();
+ }
+ }
+
+ public boolean willAutoCommitGenerateFlow() throws org.apache.derby.client.am.SqlException {
+ if (!autoCommit_) {
+ return false;
+ }
+ if (disallowLocalCommitRollback_()) {
+ return false;
+ }
+ return true;
+ }
+
+ // precondition: autoCommit_ is true
+ void writeAutoCommit() throws SqlException {
+ if (willAutoCommitGenerateFlow()) {
+ writeCommit();
+ }
+ }
+
+ public void writeCommit() throws SqlException {
+ if (isXAConnection_) {
+ if ((xaState_ == XA_LOCAL) ||
+ (xaState_ == XA_LOCAL_START_SENT)) {
+ writeLocalXACommit_();
+ }
+ } else {
+ writeLocalCommit_();
+ }
+ }
+
+ // precondition: autoCommit_ is true
+ void readAutoCommit() throws SqlException {
+ if (willAutoCommitGenerateFlow()) {
+ readCommit();
+ }
+ }
+
+ public void readCommit() throws SqlException {
+ if (isXAConnection_) {
+ if ((xaState_ == XA_LOCAL) ||
+ (xaState_ == XA_LOCAL_START_SENT)) {
+ readLocalXACommit_();
+ setXAState(XA_OPEN_IDLE);
+ }
+ } else {
+ readLocalCommit_();
+ }
+ }
+
+ synchronized public void rollback() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "rollback");
+ }
+ checkForInvalidXAStateOnCommitOrRollback();
+ checkForClosedConnection();
+ flowRollback();
+ }
+
+ // Even if we're not in a transaction, all open result sets will be closed.
+ // So we could probably just return if we're not in a transaction
+ // using the following code:
+ // if (!this.inUnitOfWork)
+ // return;
+ // But we'll just play it safe, and blindly flow the rollback.
+ // We won't try to be "too smart", if the user requests a rollback, we'll flow a rollback,
+ // regardless of whether or not we're in a unit of work or in auto-commit mode.
+ //
+ // Per JDBC specification (see javadoc for Connection.rollback()):
+ // "This method should be used only when auto-commit mode has been disabled."
+ // However, rather than trying to be too smart, we'll just flow the rollback anyway
+ // before throwing an exception.
+ // As a side-effect of invoking rollback() in auto-commit mode,
+ // we'll close all open result sets on this connection in the rollbackEvent().
+ //
+ protected void flowRollback() throws SqlException {
+ if (isXAConnection_) {
+ agent_.beginWriteChainOutsideUOW();
+ writeRollback();
+ agent_.flowOutsideUOW();
+ readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
+ agent_.endReadChain();
+ } else {
+ agent_.beginWriteChain(null);
+ writeRollback();
+ agent_.flow(null);
+ readRollback(); // This method will invoke the rollbackEvent() callback from the material layer.
+ agent_.endReadChain();
+ }
+ }
+
+ public void writeRollback() throws SqlException {
+ if (isXAConnection_) {
+ writeLocalXARollback_();
+ } else {
+ writeLocalRollback_();
+ }
+ }
+
+ public void readRollback() throws SqlException {
+ if (isXAConnection_) {
+ readLocalXARollback_();
+ setXAState(XA_OPEN_IDLE);
+ } else {
+ readLocalRollback_();
+ }
+ }
+
+ synchronized public void close() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "close");
+ }
+ closeX();
+ }
+
+ void checkForTransactionInProgress() throws SqlException {
+ // The following precondition matches CLI semantics, see SQLDisconnect()
+ if (!autoCommit_ && inUnitOfWork_ && !allowCloseInUOW_()) {
+ throw new SqlException(agent_.logWriter_,
+ "java.sql.Connection.close() requested while a transaction is in progress on the connection." +
+ "The transaction remains active, and the connection cannot be closed.");
+ }
+ }
+
+ // This is a no-op if the connection is already closed.
+ synchronized public void closeX() throws SqlException {
+ if (!open_) {
+ return;
+ }
+ closeResourcesX();
+ }
+
+ // Close physical socket or attachment even if connection is marked close.
+ // Used by ClientPooledConnection.close().
+ synchronized public void closeResources() throws SqlException {
+ if (open_ || (!open_ && availableForReuse_)) {
+ availableForReuse_ = false;
+ closeResourcesX();
+ }
+ }
+
+ private void closeResourcesX() throws SqlException {
+ checkForTransactionInProgress();
+ resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
+ SqlException accumulatedExceptions = null;
+ if (setTransactionIsolationStmt != null) {
+ try {
+ setTransactionIsolationStmt.close();
+ } catch (SqlException se) {
+ accumulatedExceptions = se;
+ }
+ }
+ try {
+ flowClose();
+ } catch (SqlException e) {
+ accumulatedExceptions =
+ Utils.accumulateSQLException(e, accumulatedExceptions);
+ }
+
+ markClosed();
+ try {
+ agent_.close();
+ } catch (SqlException e) {
+ throw Utils.accumulateSQLException(e, accumulatedExceptions);
+ }
+ }
+
+ protected abstract boolean isGlobalPending_();
+
+ // Just like closeX except the socket is not pulled.
+ // Physical resources are not closed.
+ synchronized public void closeForReuse() throws SqlException {
+ if (!open_) {
+ return;
+ }
+ checkForTransactionInProgress();
+ resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
+ SqlException accumulatedExceptions = null;
+ try {
+ flowClose();
+ } catch (SqlException e) {
+ accumulatedExceptions = e;
+ }
+ if (open_) {
+ markClosedForReuse();
+ }
+ if (accumulatedExceptions != null) {
+ throw accumulatedExceptions;
+ }
+ }
+
+ private void flowClose() throws SqlException {
+ agent_.beginWriteChainOutsideUOW();
+ if (doCloseStatementsOnClose_()) {
+ writeCloseStatements();
+ }
+ if (autoCommit_) {
+ writeAutoCommit();
+ }
+ agent_.flowOutsideUOW();
+ if (doCloseStatementsOnClose_()) {
+ readCloseStatements();
+ }
+ if (autoCommit_) {
+ readAutoCommit();
+ }
+ agent_.endReadChain();
+ }
- isolation_ = Configuration.defaultIsolation;
- autoCommit_ = true;
- inUnitOfWork_ = false;
+ protected abstract void markClosed_();
- loginTimeout_ = ds.getLoginTimeout();
- dataSource_ = ds;
+ public void markClosed() // called by LogicalConnection.close()
+ {
+ open_ = false;
+ inUnitOfWork_ = false;
+ markStatementsClosed();
+ CommitAndRollbackListeners_.clear();
+ RollbackOnlyListeners_.clear();
+ markClosed_();
+ }
+
+
+ private void markClosedForReuse() {
+ availableForReuse_ = true;
+ markClosed();
+ }
+
+ private void markStatementsClosed() {
+ for (java.util.ListIterator i = openStatements_.listIterator(); i.hasNext();) {
+ Statement stmt = (Statement) i.next();
+ stmt.markClosed();
+ i.remove();
+ }
+ }
+
+ private void writeCloseStatements() throws SqlException {
+ for (java.util.ListIterator i = openStatements_.listIterator(); i.hasNext();) {
+ ((Statement) i.next()).writeClose(false); // false means don't permit auto-commits
+ }
+ }
+
+ private void readCloseStatements() throws SqlException {
+ for (java.util.ListIterator i = openStatements_.listIterator(); i.hasNext();) {
+ ((Statement) i.next()).readClose(false); // false means don't permit auto-commits
+ }
+ }
+
+
+ public boolean isClosed() {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "isClosed", !open_);
+ }
+ return !open_;
+ }
+
+ public boolean isClosedX() {
+ return !open_;
+ }
+
+ private static String DERBY_TRANSACTION_REPEATABLE_READ = "RS";
+ private static String DERBY_TRANSACTION_SERIALIZABLE = "RR";
+ private static String DERBY_TRANSACTION_READ_COMMITTED = "CS";
+ private static String DERBY_TRANSACTION_READ_UNCOMMITTED = "UR";
+
+ synchronized public void setTransactionIsolation(int level) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setTransactionIsolation", level);
+ }
+ // Per jdbc spec (see java.sql.Connection.close() javadoc).
+ checkForClosedConnection();
+
+ // Javadoc for this method:
+ // If this method is called during a transaction, the result is implementation-defined.
+ //
+ //
+ // REPEATABLE_READ = JDBC: TRANSACTION_SERIALIZABLE, DERBY: RR, PROTOCOL: repeatable read
+ // READ_STABILITY = JDBC: TRANSACTION_REPEATABLE_READ, DERBY: RS, PROTOCOL: All
+ // CURSOR_STABILITY = JDBC: TRANSACTION_READ_COMMITTED, DERBY: CS, PROTOCOL: Cursor stability
+ // UNCOMMITTED_READ = JDBC: TRANSACTION_READ_UNCOMMITTED, DERBY: UR , PROTOCOL: Change
+ // NO_COMMIT = JDBC: TRANSACTION_NONE, DERBY: NC, PROTOCOL: No commit
+ //
+ String levelString = null;
+ switch (level) {
+ case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
+ levelString = DERBY_TRANSACTION_REPEATABLE_READ;
+ break;
+ case java.sql.Connection.TRANSACTION_READ_COMMITTED:
+ levelString = DERBY_TRANSACTION_READ_COMMITTED;
+ break;
+ case java.sql.Connection.TRANSACTION_SERIALIZABLE:
+ levelString = DERBY_TRANSACTION_SERIALIZABLE;
+ break;
+ case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
+ levelString = DERBY_TRANSACTION_READ_UNCOMMITTED;
+ break;
+ // Per javadoc:
+ // Note that Connection.TRANSACTION_NONE cannot be used because it specifies that transactions are not supported.
+ case java.sql.Connection.TRANSACTION_NONE:
+ default:
+ throw new SqlException(agent_.logWriter_,
+ "Transaction isolation level " + level + " is an invalid argument for java.sql.Connection.setTransactionIsolation()." +
+ " See Javadoc specification for a list of valid arguments.", "XJ045");
+ }
+ if (setTransactionIsolationStmt == null) {
+ setTransactionIsolationStmt =
+ createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_);
+ }
+ setTransactionIsolationStmt.executeUpdate("SET CURRENT ISOLATION = " + levelString);
+
+ isolation_ = level;
+
+ }
+
+ public int getTransactionIsolation() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getTransactionIsolation", isolation_);
+ }
+ return isolation_;
+ }
+
+ public java.sql.SQLWarning getWarnings() {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getWarnings", warnings_);
+ }
+ return warnings_;
+ }
+
+ synchronized public void clearWarnings() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "clearWarnings");
+ }
+ clearWarningsX();
+ }
+
+ // An untraced version of clearWarnings()
+ public void clearWarningsX() throws SqlException {
+ warnings_ = null;
+ accumulated440ForMessageProcFailure_ = false;
+ accumulated444ForMessageProcFailure_ = false;
+ accumulatedSetReadOnlyWarning_ = false;
+ }
+
+ //======================================================================
+ // Advanced features:
+
+ public java.sql.DatabaseMetaData getMetaData() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getMetaData", databaseMetaData_);
+ }
+ return databaseMetaData_;
+ }
+
+ synchronized public void setReadOnly(boolean readOnly) throws SqlException {
+ // This is a hint to the driver only, so this request is silently ignored.
+ // PROTOCOL can only flow a set-read-only before the connection is established.
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setReadOnly", readOnly);
+ }
+ checkForClosedConnection();
+ }
+
+ public boolean isReadOnly() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "isReadOnly", jdbcReadOnly_);
+ }
+ return false;
+ }
+
+ synchronized public void setCatalog(String catalog) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setCatalog", catalog);
+ }
+ checkForClosedConnection();
+ // Per jdbc spec: if the driver does not support catalogs, it will silently ignore this request.
+ }
+
+ public String getCatalog() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getCatalog", (String) null);
+ }
+ return null;
+ }
+
+ //--------------------------JDBC 2.0-----------------------------
+
+ synchronized public java.sql.Statement createStatement(int resultSetType,
+ int resultSetConcurrency) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "createStatement", resultSetType, resultSetConcurrency);
+ }
+ Statement s = createStatementX(resultSetType, resultSetConcurrency, resultSetHoldability_);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "createStatement", s);
+ }
+ return s;
+ }
+
+ synchronized public java.sql.PreparedStatement prepareStatement(String sql,
+ int resultSetType,
+ int resultSetConcurrency) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql, resultSetType, resultSetConcurrency);
+ }
+ PreparedStatement ps = prepareStatementX(sql,
+ resultSetType,
+ resultSetConcurrency,
+ resultSetHoldability_,
+ java.sql.Statement.NO_GENERATED_KEYS,
+ null);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareStatement", ps);
+ }
+ return ps;
+ }
+
+ synchronized public java.sql.CallableStatement prepareCall(String sql,
+ int resultSetType,
+ int resultSetConcurrency) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareCall", sql, resultSetType, resultSetConcurrency);
+ }
+ CallableStatement cs = prepareCallX(sql, resultSetType, resultSetConcurrency, resultSetHoldability_);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareCall", cs);
+ }
+ return cs;
+ }
+
+ synchronized public CallableStatement prepareMessageProc(String sql) throws SqlException {
+ checkForClosedConnection();
+
+ CallableStatement cs = prepareCallX(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_);
+ return cs;
+ }
+
+ // Per jdbc spec, when a result set type is unsupported, we downgrade and
+ // issue a warning rather than to throw an exception.
+ private int downgradeResultSetType(int resultSetType) {
+ if (resultSetType == java.sql.ResultSet.TYPE_SCROLL_SENSITIVE) {
+ accumulateWarning(new SqlWarning(agent_.logWriter_, "Scroll sensitive result sets are not supported by server; remapping to forward-only cursor"));
+ return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+ }
+ return resultSetType;
+ }
+
+ // Per jdbc spec, when a result set concurrency is unsupported, we downgrade and
+ // issue a warning rather than to throw an exception.
+ private int downgradeResultSetConcurrency(int resultSetConcurrency, int resultSetType) {
+ if (resultSetConcurrency == java.sql.ResultSet.CONCUR_UPDATABLE &&
+ resultSetType == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
+ accumulateWarning(new SqlWarning(agent_.logWriter_, "Insensitive updatable result sets are not supported by server; remapping to insensitive read-only cursor"));
+ return java.sql.ResultSet.CONCUR_READ_ONLY;
+ }
+ return resultSetConcurrency;
+ }
+
+ public java.util.Map getTypeMap() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "getTypeMap");
+ }
+ checkForClosedConnection();
+ java.util.Map map = new java.util.HashMap();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getTypeMap", map);
+ }
+ return map;
+ }
+
+ synchronized public void setTypeMap(java.util.Map map) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setTypeMap", map);
+ }
+ checkForClosedConnection();
+ throw new SqlException(agent_.logWriter_, "Connection.setTypeMap is not supported");
+ }
+
+ //--------------------------JDBC 3.0-----------------------------
+
+ synchronized public void setHoldability(int holdability) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setHoldability", holdability);
+ }
+ checkForClosedConnection();
+ resultSetHoldability_ = holdability;
+ }
+
+ public int getHoldability() throws SqlException {
+ checkForClosedConnection();
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "getHoldability", resultSetHoldability_);
+ }
+ return resultSetHoldability_;
+ }
+
+ public int dncGeneratedSavepointId_;
+ // generated name used internally for unnamed savepoints
+ public static final String dncGeneratedSavepointNamePrefix__ = "DNC_GENENERATED_NAME_";
+
+ synchronized public java.sql.Savepoint setSavepoint() throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setSavepoint");
+ }
+ checkForClosedConnection();
+ if (autoCommit_) // Throw exception if auto-commit is on
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot set savepoint when in auto-commit mode.");
+ } else if (xaState_ == XA_PENDING_START ||
+ xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot set savepoint during distributed transaction.");
+ }
+ // create an un-named savepoint.
+ if ((++dncGeneratedSavepointId_) < 0) {
+ dncGeneratedSavepointId_ = 1; // restart from 1 when overflow.
+ }
+ Object s = setSavepointX(new Savepoint(agent_, dncGeneratedSavepointId_));
+ return (java.sql.Savepoint) s;
+ }
+
+ synchronized public java.sql.Savepoint setSavepoint(String name) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "setSavepoint", name);
+ }
+ checkForClosedConnection();
+ if (name == null) // Throw exception if savepoint name is null
+ {
+ throw new SqlException(agent_.logWriter_, "Named savepoint needs a none-null name.");
+ } else if (autoCommit_) // Throw exception if auto-commit is on
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot set savepoint when in auto-commit mode.");
+ } else if (xaState_ == XA_PENDING_START ||
+ xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot set savepoint during distributed transaction.");
+ }
+ // create a named savepoint.
+ Object s = setSavepointX(new Savepoint(agent_, name));
+ return (java.sql.Savepoint) s;
+ }
+
+ private Savepoint setSavepointX(Savepoint savepoint) throws SqlException {
+ // Construct and flow a savepoint statement to server.
+ Statement stmt = null;
+ try {
+ stmt = (Statement) createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_);
+ String savepointName;
+ try {
+ savepointName = savepoint.getSavepointName();
+ } catch (SqlException e) {
+ // generate the name for an un-named savepoint.
+ savepointName = dncGeneratedSavepointNamePrefix__ +
+ savepoint.getSavepointId();
+ }
+ String sql = "SAVEPOINT \"" + savepointName + "\" ON ROLLBACK RETAIN CURSORS";
+ stmt.executeX(sql);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.closeX();
+ } catch (SqlException doNothing) {
+ }
+ }
+ }
+
+ return savepoint;
+ }
+
+ synchronized public void rollback(java.sql.Savepoint savepoint) throws SqlException {
+ int saveXaState = xaState_;
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "rollback", savepoint);
+ }
+ checkForClosedConnection();
+ if (savepoint == null) // Throw exception if savepoint is null
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot rollback to a null savepoint.");
+ } else if (autoCommit_) // Throw exception if auto-commit is on
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot rollback to a savepoint when in auto-commit mode.");
+ } else if (xaState_ == XA_PENDING_START ||
+ xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot rollback to a savepoint during distributed transaction.");
+ }
+ // Only allow to rollback to a savepoint from the connection that create the savepoint.
+ try {
+ if (this != ((Savepoint) savepoint).agent_.connection_) {
+ throw new SqlException(agent_.logWriter_,
+ "Rollback to a savepoint not created by this connection.");
+ }
+ } catch (java.lang.ClassCastException e) { // savepoint is not an instance of am.Savepoint
+ throw new SqlException(agent_.logWriter_,
+ "Rollback to a savepoint not created by this connection.");
+ }
+
+ // Construct and flow a savepoint rollback statement to server.
+ Statement stmt = null;
+ try {
+ stmt = createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_);
+ String savepointName;
+ try {
+ savepointName = ((Savepoint) savepoint).getSavepointName();
+ } catch (SqlException e) {
+ // generate the name for an un-named savepoint.
+ savepointName = dncGeneratedSavepointNamePrefix__ +
+ ((Savepoint) savepoint).getSavepointId();
+ }
+ String sql = "ROLLBACK TO SAVEPOINT \"" + savepointName + "\"";
+ stmt.executeX(sql);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.closeX();
+ } catch (SqlException doNothing) {
+ }
+ }
+ xaState_ = saveXaState;
+ }
+ }
+
+ synchronized public void releaseSavepoint(java.sql.Savepoint savepoint) throws SqlException {
+ int saveXaState = xaState_;
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "releaseSavepoint", savepoint);
+ }
+ checkForClosedConnection();
+ if (savepoint == null) // Throw exception if savepoint is null
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot release a null savepoint.");
+ } else if (autoCommit_) // Throw exception if auto-commit is on
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot release a savepoint when in auto-commit mode.");
+ } else if (xaState_ == XA_PENDING_START ||
+ xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
+ {
+ throw new SqlException(agent_.logWriter_, "Cannot release a savepoint during distributed transaction.");
+ }
+ // Only allow to release a savepoint from the connection that create the savepoint.
+ try {
+ if (this != ((Savepoint) savepoint).agent_.connection_) {
+ throw new SqlException(agent_.logWriter_,
+ "Cannot release a savepoint that was not created by this connection.");
+ }
+ } catch (java.lang.ClassCastException e) { // savepoint is not an instance of am.Savepoint
+ throw new SqlException(agent_.logWriter_,
+ "Cannot release a savepoint that was not created by this connection.");
+ }
+
+ // Construct and flow a savepoint release statement to server.
+ Statement stmt = null;
+ try {
+ stmt = (Statement) createStatementX(java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_);
+ String savepointName;
+ try {
+ savepointName = ((Savepoint) savepoint).getSavepointName();
+ } catch (SqlException e) {
+ // generate the name for an un-named savepoint.
+ savepointName = dncGeneratedSavepointNamePrefix__ +
+ ((Savepoint) savepoint).getSavepointId();
+ }
+ String sql = "RELEASE SAVEPOINT \"" + savepointName + "\"";
+ stmt.executeX(sql);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.closeX();
+ } catch (SqlException doNothing) {
+ }
+ }
+ xaState_ = saveXaState;
+ }
+ }
+
+ synchronized public java.sql.Statement createStatement(int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "createStatement", resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+ Statement s = createStatementX(resultSetType, resultSetConcurrency, resultSetHoldability);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "createStatement", s);
+ }
+ return s;
+ }
+
+ private Statement createStatementX(int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException {
+ checkForClosedConnection();
+ resultSetType = downgradeResultSetType(resultSetType);
+ resultSetConcurrency = downgradeResultSetConcurrency(resultSetConcurrency, resultSetType);
+ Statement s = newStatement_(resultSetType, resultSetConcurrency, resultSetHoldability);
+ s.cursorAttributesToSendOnPrepare_ = s.cacheCursorAttributesToSendOnPrepare();
+ openStatements_.add(s);
+ return s;
+ }
+
+ // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
+ // right thing to do here... because if property on the dataSource changes, we may have
+ // to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
+ protected void resetStatement(Statement s) throws SqlException {
+ String cursorAttributesToSendOnPrepare = s.cursorAttributesToSendOnPrepare_;
+ resetStatement_(s, s.resultSetType_, s.resultSetConcurrency_, s.resultSetHoldability_);
+ s.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
+ }
+
+ synchronized public java.sql.PreparedStatement prepareStatement(String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+ PreparedStatement ps = prepareStatementX(sql,
+ resultSetType,
+ resultSetConcurrency,
+ resultSetHoldability,
+ java.sql.Statement.NO_GENERATED_KEYS,
+ null);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareStatement", ps);
+ }
+ return ps;
+ }
+
+ // used by DBMD
+ PreparedStatement prepareStatementX(String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability,
+ int autoGeneratedKeys,
+ String[] columnNames) throws SqlException {
+ checkForClosedConnection();
+ checkAutoGeneratedKeysParameters(autoGeneratedKeys, columnNames);
+ resultSetType = downgradeResultSetType(resultSetType);
+ resultSetConcurrency = downgradeResultSetConcurrency(resultSetConcurrency, resultSetType);
+ PreparedStatement ps = newPreparedStatement_(sql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnNames);
+ ps.cursorAttributesToSendOnPrepare_ = ps.cacheCursorAttributesToSendOnPrepare();
+ ps.prepare();
+ openStatements_.add(ps);
+ return ps;
+ }
+
+ // not sure if holding on to cursorAttributesToSendOnPrepare and restoring it is the
+ // right thing to do here... because if property on the dataSource changes, we may have
+ // to send different attributes, i.e. SENSITIVE DYNAMIC, instead of SENSITIVE STATIC.
+ protected void resetPrepareStatement(PreparedStatement ps) throws SqlException {
+ String cursorAttributesToSendOnPrepare = ps.cursorAttributesToSendOnPrepare_;
+ resetPreparedStatement_(ps, ps.sql_, ps.resultSetType_, ps.resultSetConcurrency_, ps.resultSetHoldability_, ps.autoGeneratedKeys_, ps.generatedKeysColumnNames_);
+ ps.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
+ ps.prepare();
+ }
+
+ synchronized public java.sql.CallableStatement prepareCall(String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareCall", sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+ CallableStatement cs = prepareCallX(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareCall", cs);
+ }
+ return cs;
+ }
+
+ private CallableStatement prepareCallX(String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException {
+ checkForClosedConnection();
+ resultSetType = downgradeResultSetType(resultSetType);
+ resultSetConcurrency = downgradeResultSetConcurrency(resultSetConcurrency, resultSetType);
+ CallableStatement cs = newCallableStatement_(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ cs.cursorAttributesToSendOnPrepare_ = cs.cacheCursorAttributesToSendOnPrepare();
+ cs.prepare();
+ openStatements_.add(cs);
+ return cs;
+ }
+
+ protected void resetPrepareCall(CallableStatement cs) throws SqlException {
+ String cursorAttributesToSendOnPrepare = cs.cursorAttributesToSendOnPrepare_;
+ resetCallableStatement_(cs, cs.sql_, cs.resultSetType_, cs.resultSetConcurrency_, cs.resultSetHoldability_);
+ cs.cursorAttributesToSendOnPrepare_ = cursorAttributesToSendOnPrepare;
+ cs.prepare();
+ }
+
+ public java.sql.PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql, autoGeneratedKeys);
+ }
+ PreparedStatement ps = prepareStatementX(sql,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_,
+ autoGeneratedKeys,
+ null);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareStatement", ps);
+ }
+ return ps;
+ }
+
+ public java.sql.PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql, columnIndexes);
+ }
+ checkForClosedConnection();
+ throw new SqlException(agent_.logWriter_, "Driver not capable");
+ }
+
+ public java.sql.PreparedStatement prepareStatement(String sql, String columnNames[]) throws SqlException {
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceEntry(this, "prepareStatement", sql, columnNames);
+ }
+ PreparedStatement ps = prepareStatementX(sql,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ resultSetHoldability_,
+ java.sql.Statement.RETURN_GENERATED_KEYS,
+ columnNames);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceExit(this, "prepareStatement", ps);
+ }
+ return ps;
+ }
+
+
+ // ---------------------------------------------------------------------------
+
+ protected abstract boolean allowCloseInUOW_();
+
+ protected abstract boolean doCloseStatementsOnClose_();
+
+ public abstract SectionManager newSectionManager(String collection,
+ Agent agent,
+ String databaseName);
+ //--------------------Abstract material factory methods-----------------
+
+ protected abstract Agent newAgent_(LogWriter logWriter, int loginTimeout, String serverName, int portNumber) throws SqlException;
+
+
+ protected abstract DatabaseMetaData newDatabaseMetaData_();
+
+ protected abstract Statement newStatement_(int type,
+ int concurrency,
+ int holdability) throws SqlException;
+
+ protected abstract void resetStatement_(Statement statement,
+ int type,
+ int concurrency,
+ int holdability) throws SqlException;
+
+
+ protected abstract PreparedStatement newPositionedUpdatePreparedStatement_(String sql, Section section) throws SqlException;
+
+ protected abstract PreparedStatement newPreparedStatement_(String sql,
+ int type,
+ int concurrency,
+ int holdability,
+ int autoGeneratedKeys,
+ String[] columnNames) throws SqlException;
+
+ protected abstract void resetPreparedStatement_(PreparedStatement ps,
+ String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability,
+ int autoGeneratedKeys,
+ String[] columnNames) throws SqlException;
+
+ protected abstract CallableStatement newCallableStatement_(String sql,
+ int type,
+ int concurrency,
+ int holdability) throws SqlException;
+
+ protected abstract void resetCallableStatement_(CallableStatement cs,
+ String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SqlException;
+
+ // ----------------------- abstract box car and callback methods ---------------------
+ // All callbacks must be client-side only operations.
+
+
+ public void completeConnect() throws SqlException {
+ open_ = true;
+ databaseMetaData_ = newDatabaseMetaData_();
+
+ agent_.sectionManager_ =
+ newSectionManager("NULLID",
+ agent_,
+ databaseName_);
+ if (agent_.loggingEnabled()) {
+ agent_.logWriter_.traceConnectExit(this);
+ }
+ }
+
+ public abstract void writeCommitSubstitute_() throws SqlException;
+
+ public abstract void readCommitSubstitute_() throws SqlException;
+
+ public abstract void writeLocalXAStart_() throws SqlException;
+
+ public abstract void readLocalXAStart_() throws SqlException;
+
+ public abstract void writeLocalXACommit_() throws SqlException;
+
+ public abstract void readLocalXACommit_() throws SqlException;
+
+ public abstract void writeLocalCommit_() throws SqlException;
+
+ public abstract void readLocalCommit_() throws SqlException;
+
+ public void completeLocalCommit() {
+ for (java.util.Iterator i = CommitAndRollbackListeners_.iterator(); i.hasNext();) {
+ UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
+ listener.completeLocalCommit(i);
+ }
+ inUnitOfWork_ = false;
+ }
+
+ public abstract void writeLocalRollback_() throws SqlException;
+
+ public abstract void readLocalRollback_() throws SqlException;
+
+ // A callback for certain non-fatal exceptions that occur when parsing error replies.
+ // This is a client-side only operation.
+ // This method will only throw an exception on bug check.
+ public void completeLocalRollback() {
+ for (java.util.Iterator i = CommitAndRollbackListeners_.iterator(); i.hasNext();) {
+ UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
+ listener.completeLocalRollback(i);
+ }
+ for (java.util.Iterator i = RollbackOnlyListeners_.iterator(); i.hasNext();) {
+ UnitOfWorkListener listener = (UnitOfWorkListener) i.next();
+ listener.completeLocalRollback(i);
+ }
+ inUnitOfWork_ = false;
+ }
+
+
+ public abstract void writeLocalXARollback_() throws SqlException;
+
+ public abstract void readLocalXARollback_() throws SqlException;
+
+ public void writeTransactionStart(Statement statement) throws SqlException {
+ }
+
+ public void readTransactionStart() throws SqlException {
+ completeTransactionStart();
+ }
+
+ void completeTransactionStart() {
+ inUnitOfWork_ = true;
+ }
+
+ // Occurs autonomously
+ public void completeAbnormalUnitOfWork() {
+ completeLocalRollback();
+ }
+
+ // Called by Connection.close(), NetConnection.errorRollbackDisconnect().
+ // The Agent's client-side resources associated with database connection are reclaimed (eg. socket).
+ // And this connection and all associated statements and result sets are marked closed.
+ // This is a client-side only operation.
+ // This method will only throw an exception if the agent cannot be closed.
+ public void completeChainBreakingDisconnect() {
+ open_ = false;
+ completeLocalRollback();
+ markStatementsClosed();
+ }
+
+ public void completeSqlca(Sqlca sqlca) {
+ if (sqlca == null) {
+ } else if (sqlca.getSqlCode() > 0) {
+ accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca));
+ } else if (sqlca.getSqlCode() < 0) {
+ agent_.accumulateReadException(new SqlException(agent_.logWriter_, sqlca));
+ }
+ }
+
+ public abstract void addSpecialRegisters(String s);
+
+ // can this only be called by the PooledConnection
+ // can this be called on a closed connection
+ // can this be called in a unit of work
+ // can this be called from within a stored procedure
+ //
+ synchronized public void reset(LogWriter logWriter, String user, String password, ClientDataSource ds, boolean recomputeFromDataSource) throws SqlException {
+ if (logWriter != null) {
+ logWriter.traceConnectResetEntry(this, logWriter, user, (ds != null) ? ds : dataSource_);
+ }
+ try {
+ reset_(logWriter, user, password, ds, recomputeFromDataSource);
+ } catch (SqlException sqle) {
+ DisconnectException de = new DisconnectException(agent_, "An error occurred during connect reset and the connection has been terminated. See chained exceptions for details.");
+ de.setNextException(sqle);
+ throw de;
+ }
}
- // property isXAConnection_
- // leave set to current value. this will impact which connect reset flows are used.
-
- xaState_ = XA_OPEN_IDLE;
- if (recomputeFromDataSource)
- this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
- }
+ synchronized public void reset(LogWriter logWriter, ClientDataSource ds, boolean recomputeFromDataSource) throws SqlException {
+ if (logWriter != null) {
+ logWriter.traceConnectResetEntry(this, logWriter, null, (ds != null) ? ds : dataSource_);
+ }
+ try {
+ reset_(logWriter, ds, recomputeFromDataSource);
+ } catch (SqlException sqle) {
+ DisconnectException de = new DisconnectException(agent_, "An error occurred during connect reset and the connection has been terminated. See chained exceptions for details.");
+ de.setNextException(sqle);
+ throw de;
+ }
+ }
- protected void resetConnection (LogWriter logWriter,
- String databaseName,
- java.util.Properties properties) throws SqlException
- {
- // clearWarningsX() will re-initialize the following properties
- // warnings_, accumulated440ForMessageProcFailure_,
- // accumulated444ForMessageProcFailure_, and accumulatedSetReadOnlyWarning_
- clearWarningsX();
+ synchronized public void lightReset() throws SqlException {
+ if (!open_ && !availableForReuse_) {
+ return;
+ }
+ open_ = true;
+ availableForReuse_ = false;
+ }
- databaseName_ = databaseName;
- user_ = ClientDataSource.getUser(properties);
+ abstract protected void reset_(LogWriter logWriter, String user, String password, ClientDataSource ds, boolean recomputerFromDataSource) throws SqlException;
- retrieveMessageText_ = ClientDataSource.getRetrieveMessageText(properties);
+ abstract protected void reset_(LogWriter logWriter, ClientDataSource ds, boolean recomputerFromDataSource) throws SqlException;
+ protected void completeReset(boolean isDeferredReset, boolean recomputeFromDataSource) throws SqlException {
+ open_ = true;
- // property encryptionManager_
- // if needed this will later be initialized by NET calls to initializePublicKeyForEncryption()
- encryptionManager_ = null;
+ completeLocalRollback(); // this will close the cursors if the physical connection hadn't been closed for reuse properly
- // property: open_
- // this should already be true
+ // Reopen physical statement resources associated with previous uses of this physical connection.
+ // Notice that these physical statements may not belong to this logical connection.
+ // Iterate through the physical statements and re-enable them for reuse.
- isolation_ = Configuration.defaultIsolation;
- autoCommit_ = true;
- inUnitOfWork_ = false;
+ for (java.util.Iterator i = openStatements_.iterator(); i.hasNext();) {
+ Object o = i.next();
+ ((Statement) o).reset(recomputeFromDataSource);
- // property isXAConnection_
- // leave set to current value. this will impact which connect reset flows are used.
+ }
- xaState_ = XA_OPEN_IDLE;
+ if (!isDeferredReset && agent_.loggingEnabled()) {
+ agent_.logWriter_.traceConnectResetExit(this);
+ }
+ }
- this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
- }
+ //-------------------------------helper methods-------------------------------
+ protected void checkForClosedConnection() throws SqlException {
+ if (!open_) {
+ agent_.checkForDeferredExceptions();
+ throw new SqlException(agent_.logWriter_, "invalid operation: connection closed");
+ } else {
+ agent_.checkForDeferredExceptions();
+ }
+ }
+ void checkAutoGeneratedKeysParameters(int autoGeneratedKeys, String[] columnNames) throws SqlException {
+ if (autoGeneratedKeys != java.sql.Statement.NO_GENERATED_KEYS &&
+ autoGeneratedKeys != java.sql.Statement.RETURN_GENERATED_KEYS) {
+ throw new SqlException(agent_.logWriter_, "Invalid argument: " +
+ "Statement auto-generated keys value " + autoGeneratedKeys +
+ " is invalid.");
+ }
- // For jdbc 1 connections
- protected Connection (LogWriter logWriter,
- int driverManagerLoginTimeout,
- String serverName,
- int portNumber,
- String databaseName,
- java.util.Properties properties) throws SqlException
- {
- if (logWriter != null) logWriter.traceConnectEntry (serverName, portNumber, databaseName, properties);
- org.apache.derby.client.am.Configuration.checkForExceptionsFromLoadConfiguration (logWriter);
+ if (columnNames != null) {
+ throw new SqlException(agent_.logWriter_, "Driver not capable");
+ }
- databaseName_ = databaseName;
+ }
- // Extract common properties.
- user_ = ClientDataSource.getUser (properties);
- retrieveMessageText_ = ClientDataSource.getRetrieveMessageText (properties);
+ public boolean isXAConnection() {
+ return isXAConnection_;
+ }
- loginTimeout_ = driverManagerLoginTimeout;
- serverNameIP_ = serverName;
- portNumber_ = portNumber;
+ public int getXAState() {
+ return xaState_;
+ }
- agent_ = newAgent_ (logWriter,
- loginTimeout_,
- serverNameIP_,
- portNumber_);
- }
+ public void setXAState(int state) {
+ xaState_ = state;
+ }
- // Users are advised to call the method close() on Statement and Connection objects when they are done with them.
- // However, some users will forget, and some code may get killed before it can close these objects.
- // Therefore, if JDBC drivers have state associated with JDBC objects that need to get
- // explicitly cleared up, they should provide finalize methods to take care of them.
- // The garbage collector will call these finalize methods when the objects are found to be garbage,
- // and this will give the driver a chance to close (or otherwise clean up) the objects.
- // Note, however, that there is no guarantee that the garbage collector will ever run.
- // If that is the case, the finalizers will not be called.
- protected void finalize () throws java.lang.Throwable
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "finalize");
+ public void accumulateWarning(SqlWarning e) {
+ if (warnings_ == null) {
+ warnings_ = e;
+ } else {
+ warnings_.setNextException(e);
+ }
+ }
- // finalize() differs from close() in that it will not throw an
- // exception if a transaction is in progress.
- // finalize() also differs from close() in that it will not drive
- // an auto-commit before disconnecting.
- //
- // If a transaction is in progress, a close() request will throw an SqlException.
- // However, if a connection with an incomplete transaction is finalized,
- // or is abruptly terminated by application exit,
- // the normal rollback semantics imposed by the DERBY server are adopted.
- // So we just pull the plug and let the server handle this default semantic.
-
- if (!open_) return;
- agent_.disconnectEvent ();
- super.finalize();
- }
-
- // ---------------------------jdbc 1------------------------------------------
-
- synchronized public java.sql.Statement createStatement () throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "createStatement");
- Statement s = createStatementX (java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_);
- if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "createStatement", s);
- return s;
- }
-
- synchronized public java.sql.PreparedStatement prepareStatement (String sql) throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "prepareStatement", sql);
- PreparedStatement ps = prepareStatementX (sql,
- java.sql.ResultSet.TYPE_FORWARD_ONLY,
- java.sql.ResultSet.CONCUR_READ_ONLY,
- resultSetHoldability_,
- java.sql.Statement.NO_GENERATED_KEYS,
- null);
- if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "prepareStatement", ps);
- return ps;
- }
-
- // For internal use only. Use by updatable result set code.
- synchronized public PreparedStatement preparePositionedUpdateStatement (String sql, Section querySection) throws SqlException
- {
- checkForClosedConnection ();
- // create a net material prepared statement.
- PreparedStatement preparedStatement = newPositionedUpdatePreparedStatement_ (sql, querySection);
- preparedStatement.flowPrepareDescribeInputOutput ();
- // The positioned update statement is not added to the list of open statements,
- // because this would cause a java.util.ConcurrentModificationException when
- // iterating thru the list of open statements to call completeRollback().
- // An updatable result set is marked closed on a call to completeRollback(),
- // and would therefore need to close the positioned update statement associated with the result set which would cause
- // it to be removed from the open statements list. Resulting in concurrent modification
- // on the open statements list.
- // Notice that ordinary Statement.closeX() is never called on the positioned update statement,
- // rather markClosed() is called to avoid trying to remove the statement from the openStatements_ list.
- return preparedStatement;
- }
-
- synchronized public java.sql.CallableStatement prepareCall (String sql) throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "prepareCall", sql);
- CallableStatement cs = prepareCallX (sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_);
- if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "prepareCall", cs);
- return cs;
- }
-
- synchronized PreparedStatement prepareDynamicCatalogQuery (String sql) throws SqlException
- {
- PreparedStatement ps = newPreparedStatement_ (sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY, resultSetHoldability_, java.sql.Statement.NO_GENERATED_KEYS, null);
- ps.isCatalogQuery_ = true;
- ps.prepare ();
- openStatements_.add (ps);
- return ps;
- }
-
- public String nativeSQL (String sql) throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "nativeSQL", sql);
- String nativeSql = nativeSQLX (sql);
- if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "nativeSQL", nativeSql);
- return nativeSql;
- }
-
- synchronized public String nativeSQLX (String sql) throws SqlException
- {
- checkForClosedConnection();
- if (sql == null) throw new SqlException (agent_.logWriter_, "Null SQL string passed.");
-
- // Derby can handle the escape syntax directly so only needs escape
- // processing for { ? = CALL ....}
- String trimSql = sql.trim();
- if (trimSql.startsWith ("{"))
- {
- if (trimSql.lastIndexOf("}") >= 0)
- return trimSql.substring(1, trimSql.lastIndexOf("}"));
+ public void accumulate440WarningForMessageProcFailure(SqlWarning e) {
+ if (!accumulated440ForMessageProcFailure_) {
+ accumulateWarning(e);
+ accumulated440ForMessageProcFailure_ = true;
+ }
}
- return trimSql;
- }
+ public void accumulate444WarningForMessageProcFailure(SqlWarning e) {
+ if (!accumulated444ForMessageProcFailure_) {
+ accumulateWarning(e);
+ accumulated444ForMessageProcFailure_ = true;
+ }
+ }
- // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
- // primary usage is distinction between local and global trans. envs.;
- protected abstract boolean disallowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException;
-
- synchronized public void setAutoCommit (boolean autoCommit) throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "setAutoCommit", autoCommit);
- checkForClosedConnection();
-
- if ( disallowLocalCommitRollback_() ) {
- if (autoCommit) { // can't toggle to autocommit mode when between xars.start() and xars.end()
- throw new SqlException (agent_.logWriter_,
- "setAutoCommit(true) invalid during global transaction",
- SqlState._2D521, // Spec'ed by PROTOCOL
- SqlCode.invalidSetAutoCommitUnderXA);
- }
- }
- else {
- if (autoCommit == autoCommit_) return; // don't flow a commit if nothing changed.
- if (inUnitOfWork_) flowCommit(); // we are not between xars.start() and xars.end(), can flow commit
- }
- autoCommit_ = autoCommit;
- }
-
- public boolean getAutoCommit () throws SqlException
- {
- checkForClosedConnection();
- if (agent_.loggingEnabled()) agent_.logWriter_.traceExit (this, "getAutoCommit", autoCommit_);
- if ( disallowLocalCommitRollback_() )
- { // autoCommit is always false between xars.start() and xars.end()
- return false;
- }
- return autoCommit_;
- }
-
- synchronized public void commit () throws SqlException
- {
- if (agent_.loggingEnabled()) agent_.logWriter_.traceEntry (this, "commit");
-
- // the following XA State check must be in commit instead of commitX since
- // external application call commit, the SqlException should be thrown
- // only if an external application calls commit during a Global Transaction,
- // internal code will call commitX which will ignore the commit request
- // while in a Global transaction
- checkForInvalidXAStateOnCommitOrRollback ();
- checkForClosedConnection();
- flowCommit();
- }
-
- private void checkForInvalidXAStateOnCommitOrRollback () throws SqlException
- {
- if ( disallowLocalCommitRollback_() ) {
- throw new SqlException (agent_.logWriter_,
- "COMMIT or ROLLBACK invalid for application execution environment",
- SqlState._2D521, // Spec'ed by PROTOCOL
- SqlCode.invalidCommitOrRollbackUnderXA);
- }
- }
-
- public void flowCommit () throws SqlException
- {
- // Per JDBC specification (see javadoc for Connection.commit()):
- // "This method should be used only when auto-commit mode has been disabled."
- // However, some applications do this anyway, it is harmless, so
- // if they ask to commit, we could go ahead and flow a commit.
- // But note that rollback() is less harmless, rollback() shouldn't be used in auto-commit mode.
- // This behavior is subject to further review.
-
- // if (!this.inUnitOfWork)
- // return;
[... 1062 lines stripped ...]