db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r685141 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/impl/sql/conn/ engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/functionTests/tests/lang/
Date Tue, 12 Aug 2008 13:16:03 GMT
Author: dag
Date: Tue Aug 12 06:15:57 2008
New Revision: 685141

URL: http://svn.apache.org/viewvc?rev=685141&view=rev
Log:
DERBY-48 A connection request that has a default schema that is being created by another transaction
will fail to connect

Patch derby-48b, which limits the use of a subtransaction to the
initial default schema, other implicit schema creation is
transactional. A new testcase is added to show the latter.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java?rev=685141&r1=685140&r2=685141&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
Tue Aug 12 06:15:57 2008
@@ -498,6 +498,15 @@
 	 */
 	public String getCurrentSchemaName(Activation a);
 
+
+	/**
+	 * Return true if this schema name is the initial default schema for the
+	 * current session.
+	 * @param schemaName 
+	 * @return true
+	 */
+	public boolean isInitialDefaultSchema(String schemaName);
+
 	/**
 	 * Get the identity column value most recently generated.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=685141&r1=685140&r2=685141&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
Tue Aug 12 06:15:57 2008
@@ -1853,6 +1853,16 @@
 		return s.getSchemaName();
 	}
 
+
+	/**
+	 * @see LanguageConnectionContext#isInitialDefaultSchema
+	 */
+	public boolean isInitialDefaultSchema(String schemaName) {
+		return cachedInitialDefaultSchemaDescr.getSchemaName().
+			equals(schemaName);
+	}
+
+
 	/**
 	 * @see LanguageConnectionContext#setDefaultSchema(SchemaDescriptor sd)
 	 */

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java?rev=685141&r1=685140&r2=685141&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
Tue Aug 12 06:15:57 2008
@@ -104,81 +104,98 @@
             CreateSchemaConstantAction csca
                 = new CreateSchemaConstantAction(schemaName, (String) null);
 
-			// DERBY-48: This operation creates a schema and we don't
-			// want to hold a lock for SYSSCHEMAS for the duration of
-			// the user transaction, so we perform the creation in a
-			// nested transaction if possible.
-			TransactionController useTc    = null;
-			TransactionController nestedTc = null;
-
-			try {
-				nestedTc = tc.startNestedUserTransaction(false);
-				useTc = nestedTc;
-			} catch (StandardException e) {
-				if (SanityManager.DEBUG) {
-					SanityManager.THROWASSERT(
-						"Unexpected: not able to start nested transaction " +
-						"to auto-create schema", e);
-				}
-				useTc = tc;
-			}
+			if (activation.getLanguageConnectionContext().
+					isInitialDefaultSchema(schemaName)) {
+				// DERBY-48: This operation creates the user's initial default
+				// schema and we don't want to hold a lock for SYSSCHEMAS for
+				// the duration of the user transaction, so we perform the
+				// creation in a nested transaction if possible.
+				TransactionController useTc    = null;
+				TransactionController nestedTc = null;
 
-			// Try max twice: if nested transaction times out, try
-			// again in the outer transaction because it may be a
-			// self-lock, that is, the outer transaction may hold some
-			// lock(s) that make the nested transaction attempt to set
-			// a write lock time out.  Trying it again in the outer
-			// transaction will then succeed. If the reason is some
-			// other transaction barring us, trying again in the outer
-			// transaction will possibly time out again.
-			//
-			// Also, if creating a nested transaction failed, only try
-			// once in the outer transaction.
-			while (true) {
 				try {
-					csca.executeConstantAction(activation, useTc);
-				} catch (StandardException se) {
-					if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT)) {
-						// We don't test for SQLState.DEADLOCK or
-						// .LOCK_TIMEOUT_LOG here because a) if it is a
-						// deadlock, it may be better to expose it, and b)
-						// LOCK_TIMEOUT_LOG happens when the app has set
-						// derby.locks.deadlockTrace=true, in which case we
-						// don't want to mask the timeout.  So in both the
-						// latter cases we just throw.
-						if (useTc == nestedTc) {
+					nestedTc = tc.startNestedUserTransaction(false);
+					useTc = nestedTc;
+				} catch (StandardException e) {
+					if (SanityManager.DEBUG) {
+						SanityManager.THROWASSERT(
+							"Unexpected: not able to start nested transaction " +
+							"to auto-create schema", e);
+					}
+					useTc = tc;
+				}
 
-							// clean up after use of nested transaction,
-							// then try again in outer transaction
-							useTc = tc;
+				// Try max twice: if nested transaction times out, try
+				// again in the outer transaction because it may be a
+				// self-lock, that is, the outer transaction may hold some
+				// lock(s) that make the nested transaction attempt to set
+				// a write lock time out.  Trying it again in the outer
+				// transaction will then succeed. If the reason is some
+				// other transaction barring us, trying again in the outer
+				// transaction will possibly time out again.
+				//
+				// Also, if creating a nested transaction failed, only try
+				// once in the outer transaction.
+				while (true) {
+					try {
+						csca.executeConstantAction(activation, useTc);
+					} catch (StandardException se) {
+						if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT)) {
+							// We don't test for SQLState.DEADLOCK or
+							// .LOCK_TIMEOUT_LOG here because a) if it is a
+							// deadlock, it may be better to expose it, and b)
+							// LOCK_TIMEOUT_LOG happens when the app has set
+							// derby.locks.deadlockTrace=true, in which case we
+							// don't want to mask the timeout.  So in both the
+							// latter cases we just throw.
+							if (useTc == nestedTc) {
+
+								// clean up after use of nested transaction,
+								// then try again in outer transaction
+								useTc = tc;
+								nestedTc.destroy();
+								continue;
+							}
+						} else if (se.getMessageId()
+									   .equals(SQLState.LANG_OBJECT_ALREADY_EXISTS)) {
+							// Ignore "Schema already exists". Another thread has
+							// probably created it after we checked for it
+							break;
+						}
+
+						// We got an non-expected exception, either in
+						// the nested transaction or in the outer
+						// transaction; we had better pass that on
+						if (useTc == nestedTc) {
 							nestedTc.destroy();
-							continue;
 						}
-					} else if (se.getMessageId()
+
+						throw se;
+					}
+					break;
+				}
+
+				// We either succeeded or got LANG_OBJECT_ALREADY_EXISTS.
+				// Clean up if we did this in a nested transaction.
+				if (useTc == nestedTc) {
+					nestedTc.commit();
+					nestedTc.destroy();
+				}
+			} else {
+				// create the schema in the user transaction always
+				try {
+					csca.executeConstantAction(activation);
+				} catch (StandardException se) {
+					if (se.getMessageId()
 							.equals(SQLState.LANG_OBJECT_ALREADY_EXISTS)) {
 						// Ignore "Schema already exists". Another thread has
 						// probably created it after we checked for it
-						break;
-					}
-
-					// We got an non-expected exception, either in
-					// the nested transaction or in the outer
-					// transaction; we had better pass that on
-					if (useTc == nestedTc) {
-						nestedTc.destroy();
+					} else {
+						throw se;
 					}
-
-					throw se;
 				}
-				break;
 			}
 
-			// We either succeeded or got LANG_OBJECT_ALREADY_EXISTS.
-			// Clean up if we did this in a nested transaction.
-			if (useTc == nestedTc) {
-				nestedTc.commit();
-				nestedTc.destroy();
-			}
 
 			sd = dd.getSchemaDescriptor(schemaName, tc, true);
 		}

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java?rev=685141&r1=685140&r2=685141&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java
Tue Aug 12 06:15:57 2008
@@ -208,7 +208,40 @@
         }
     }
 
-    protected void  tearDown() throws Exception {
+    /**
+     * Test that implicit schema creation of other schemas besides
+     * the initial default schema is still transactional.
+     */
+    public void testOtherImplicitSchemaCreation () throws SQLException
+    {
+        Connection c1 = openUserConnection("newuser");
+        c1.setAutoCommit(false);
+        Statement s1 = c1.createStatement();
+
+        // Will auto-create schema OTHERSCHEMA:
+        s1.executeUpdate("create table otherschema.t1(i int)");
+        s1.close();
+        
+        JDBC.assertSingleValueResultSet(
+            c1.createStatement().executeQuery(
+                "select schemaname from sys.sysschemas " +
+                "where schemaname='OTHERSCHEMA'"),
+            "OTHERSCHEMA");
+
+        c1.rollback();
+
+        JDBC.assertEmpty(
+            c1.createStatement().executeQuery(
+                "select schemaname from sys.sysschemas " +
+                "where schemaname='OTHERSCHEMA'"));
+        
+        c1.rollback();
+        c1.close();
+    }
+
+
+
+protected void  tearDown() throws Exception {
         try {
             createStatement().executeUpdate("drop schema newuser restrict");
         } catch (SQLException e) {



Mime
View raw message