db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1574389 - in /db/derby/code/branches/10.10: ./ java/engine/org/apache/derby/iapi/sql/dictionary/ java/engine/org/apache/derby/impl/sql/catalog/ java/storeless/org/apache/derby/impl/storeless/ java/testing/org/apache/derbyTesting/functionTe...
Date Wed, 05 Mar 2014 07:57:04 GMT
Author: kahatlen
Date: Wed Mar  5 07:57:03 2014
New Revision: 1574389

URL: http://svn.apache.org/r1574389
Log:
DERBY-4160: getMetaData().getIndexInfo crashes with "ERROR X0Y68: Column 'PARAM1' already
exists."

Merged revision 1570488 from trunk.

Modified:
    db/derby/code/branches/10.10/   (props changed)
    db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
    db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
    db/derby/code/branches/10.10/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
    db/derby/code/branches/10.10/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
    db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java

Propchange: db/derby/code/branches/10.10/
------------------------------------------------------------------------------
  Merged /db/derby/code/trunk:r1570488

Modified: db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java?rev=1574389&r1=1574388&r2=1574389&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
(original)
+++ db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
Wed Mar  5 07:57:03 2014
@@ -1124,18 +1124,13 @@ public interface DataDictionary
 	 * @param spsd	The descriptor to add
 	 * @param tc			The transaction controller
 	 * @param recompile		whether to recompile or invalidate
-	 * @param updateSYSCOLUMNS indicate whether syscolumns needs to be updated
-	 *							or not.
-	 * @param firstCompilation  first time SPS is getting compiled.
 	 *
 	 * @exception StandardException		Thrown on error
 	 */
 	public void	updateSPS(
 			SPSDescriptor		spsd,
 			TransactionController	tc,
-			boolean                 recompile,
-			boolean					updateSYSCOLUMNS,
-			boolean                 firstCompilation)
+            boolean                 recompile)
 						throws StandardException;
 
 	/**

Modified: db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java?rev=1574389&r1=1574388&r2=1574389&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
(original)
+++ db/derby/code/branches/10.10/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
Wed Mar  5 07:57:03 2014
@@ -134,7 +134,7 @@ public class SPSDescriptor extends Tuple
 	 * Old code - never used.
 	 */
 	private Object			paramDefaults[];
-	private	boolean					initiallyCompilable;
+    private final boolean   initiallyCompilable;
 	private	boolean					lookedUpParams;
 	
 	private UUIDFactory				uuidFactory;
@@ -691,6 +691,8 @@ public class SPSDescriptor extends Tuple
 
 			if (!lcc.getDataDictionary().isReadOnlyUpgrade()) {
 
+                final String savepoint = lcc.getUniqueSavepointName();
+
 				// First try compiling in a nested transaction so we can 
                 // release the locks after the compilation, and not have them
                 // sit around in the parent transaction. But if we get lock 
@@ -714,6 +716,11 @@ public class SPSDescriptor extends Tuple
                     // When retrying in the user transaction, we'll wait for
                     // locks if necessary.
                     nestedTC.setNoLockWait(true);
+
+                    // Set a savepoint so that the work in the nested
+                    // transaction can be rolled back on error without
+                    // aborting the parent transaction.
+                    nestedTC.setSavePoint(savepoint, null);
 				}
 				catch (StandardException se)
 				{
@@ -722,12 +729,6 @@ public class SPSDescriptor extends Tuple
 					nestedTC = null;
 				}
 
-				// DERBY-2584: If the first attempt to compile the query fails,
-				// we need to reset initiallyCompilable to make sure the
-				// prepared plan is fully stored to disk. Save the initial
-				// value here.
-				final boolean compilable = initiallyCompilable;
-
 				try
 				{
 					prepareAndRelease(lcc, null, nestedTC);
@@ -735,7 +736,16 @@ public class SPSDescriptor extends Tuple
 				}
 				catch (StandardException se)
 				{
-					if (se.isLockTimeout())
+                    if (nestedTC != null)
+                    {
+                        // Roll back to savepoint to undo any work done by
+                        // the nested transaction. We cannot abort the nested
+                        // transaction in order to achieve the same, since
+                        // that would also abort the parent transaction.
+                        nestedTC.rollbackToSavePoint(savepoint, false, null);
+                    }
+
+                    if (nestedTC != null && se.isLockTimeout())
 					{
                         // Locks were set nowait, so a lock timeout here
                         // means that some lock request in the nested 
@@ -743,18 +753,14 @@ public class SPSDescriptor extends Tuple
                         // with a parent lock would lead to a undetected 
                         // deadlock so must give up trying in the nested
                         // transaction and retry with parent transaction.
-						if (nestedTC != null)
-						{
-                            nestedTC.commit();
-                            nestedTC.destroy();
-                            nestedTC = null;
-						}
+                        nestedTC.commit();
+                        nestedTC.destroy();
+                        nestedTC = null;
 
 						// if we couldn't do this with a nested transaction, 
                         // retry with parent-- we need to wait this time!
                         // Lock conflicts at this point are with other 
                         // transactions, so must wait.
-						initiallyCompilable = compilable;
 						prepareAndRelease(lcc, null, null);
 						updateSYSSTATEMENTS(lcc, RECOMPILE, null);
 					}
@@ -1099,24 +1105,6 @@ public class SPSDescriptor extends Tuple
 	private void updateSYSSTATEMENTS(LanguageConnectionContext lcc, int mode, TransactionController
tc)
 		throws StandardException
 	{
-		boolean					updateSYSCOLUMNS,  recompile;
-		boolean firstCompilation = false;
-		if (mode == RECOMPILE)
-		{
-			recompile = true;
-			updateSYSCOLUMNS = true;
-			if(!initiallyCompilable)
-			{
-				firstCompilation = true;
-				initiallyCompilable = true;
-			}
-		}
-		else
-		{
-			recompile = false;
-			updateSYSCOLUMNS = false;
-		}
-
 		DataDictionary dd = getDataDictionary();
 
 		if (dd.isReadOnlyUpgrade())
@@ -1132,11 +1120,7 @@ public class SPSDescriptor extends Tuple
 			tc = lcc.getTransactionExecute();
 		}
 
-		dd.updateSPS(this,
-					 tc, 
-					 recompile,
-					 updateSYSCOLUMNS,
-					 firstCompilation);
+        dd.updateSPS(this, tc, (mode == RECOMPILE));
 	}
 
 	/**

Modified: db/derby/code/branches/10.10/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java?rev=1574389&r1=1574388&r2=1574389&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
(original)
+++ db/derby/code/branches/10.10/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
Wed Mar  5 07:57:03 2014
@@ -4432,19 +4432,13 @@ public final class	DataDictionaryImpl
 	 * @param spsd	The descriptor to add
 	 * @param tc			The transaction controller
      * @param recompile Whether to recompile or invalidate
-	 * @param updateParamDescriptors If true, will update the
-	 *						parameter descriptors in SYS.SYSCOLUMNS.
-	 * @param firstCompilation  true, if Statement is getting compiled for first
-	 *                          time and SPS was created with NOCOMPILE option.
 	 *
 	 * @exception StandardException		Thrown on error
 	 */
 	public void	updateSPS(
 			SPSDescriptor			spsd,
 			TransactionController	tc,
-			boolean                 recompile,
-			boolean					updateParamDescriptors,
-			boolean                 firstCompilation)
+            boolean                 recompile)
 						throws StandardException
 	{
 		ExecIndexRow				keyRow1 = null;
@@ -4455,23 +4449,13 @@ public final class	DataDictionaryImpl
 		int[] updCols;
 		if (recompile)
 		{
-			if(firstCompilation)
-			{
-				updCols = new int[] {SYSSTATEMENTSRowFactory.SYSSTATEMENTS_VALID,
-						 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_TEXT,
-									 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_LASTCOMPILED,
-									 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_USINGTEXT,
-									 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE,
-									 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_INITIALLY_COMPILABLE};
-			}else
-			{
-
-				updCols = new int[] {SYSSTATEMENTSRowFactory.SYSSTATEMENTS_VALID,
-						 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_TEXT,
-										 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_LASTCOMPILED,
-										 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_USINGTEXT,
-										 SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE };
-			}
+            updCols = new int[] {
+                SYSSTATEMENTSRowFactory.SYSSTATEMENTS_VALID,
+                SYSSTATEMENTSRowFactory.SYSSTATEMENTS_TEXT,
+                SYSSTATEMENTSRowFactory.SYSSTATEMENTS_LASTCOMPILED,
+                SYSSTATEMENTSRowFactory.SYSSTATEMENTS_USINGTEXT,
+                SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE,
+            };
 		}
 		else 
 		{
@@ -4507,11 +4491,9 @@ public final class	DataDictionaryImpl
 					 tc);
 
 
-		/*
-		** If we don't need to update the parameter
-		** descriptors, we are done.
-		*/
-		if (!updateParamDescriptors)
+        // If this is an invalidation request, we don't need to update the
+        // parameter descriptors, so we are done.
+        if (!recompile)
 		{
 			return;
 		}
@@ -4526,58 +4508,11 @@ public final class	DataDictionaryImpl
 			return;
 		}
 
-		if(firstCompilation)
-		{
-			/*beetle:5119, reason for doing add here instead of update
-			 *is with NOCOMPILE option of create statement/boot time SPS,
-			 *SPS statement is not compiled to find out the parameter info.
-			 *Because of the parameter info was not inserted at SPSDescriptor 
-			 *creation time. As this is the first time we are compiling parameter
-			 *infor should be inserted instead of the update.
-			 */
-			addSPSParams(spsd, tc);
-		}
-		else
-		{
-			Object[] parameterDefaults = spsd.getParameterDefaults();
-
-			/* 
-			** Update each column with the new defaults and with
-			** the new datatypes.  It is possible that someone has
-			** done a drop/create on the underlying table and 
-			** changed the type of a column, which has changed
-			** the type of a parameter to our statement.
-			*/
-			int[] columnsToSet = new int[2];
-			columnsToSet[0] = SYSCOLUMNSRowFactory.SYSCOLUMNS_COLUMNDATATYPE;
-			columnsToSet[1] = SYSCOLUMNSRowFactory.SYSCOLUMNS_COLUMNDEFAULT;
-
-			UUID uuid = spsd.getUUID();
-
-			for (int index = 0; index < params.length; index++)
-			{
-				int parameterId = index + 1;
-
-			//RESOLVEAUTOINCREMENT
-				ColumnDescriptor cd = new ColumnDescriptor("PARAM" + parameterId,
-										  parameterId,	// position
-										  params[index],
-										  ((parameterDefaults == null) || // default
-										   (index >= parameterDefaults.length)) ? 
-										  (DataValueDescriptor)null :
-										  (DataValueDescriptor)parameterDefaults[index],
-										  (DefaultInfo) null,
-										  uuid,
-										  (UUID) null,
-										  0, 0, 0);
-										
-				updateColumnDescriptor(cd,
-									   cd.getReferencingUUID(), 
-									   cd.getColumnName(),
-									   columnsToSet, 
-									   tc);
-			}
-		}
+        // Update the parameter descriptors by dropping the existing ones
+        // and recreating them. If this is the first time the SPS is being
+        // compiled, the drop operation will be a no-op.
+        dropAllColumnDescriptors(spsd.getUUID(), tc);
+        addSPSParams(spsd, tc);
 	}
 
 	/**

Modified: db/derby/code/branches/10.10/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java?rev=1574389&r1=1574388&r2=1574389&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
(original)
+++ db/derby/code/branches/10.10/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
Wed Mar  5 07:57:03 2014
@@ -478,8 +478,7 @@ public class EmptyDictionary implements 
 	}
 
 	public void updateSPS(SPSDescriptor spsd, TransactionController tc,
-			boolean recompile, boolean updateSYSCOLUMNS,
-			boolean firstCompilation) throws StandardException {
+            boolean recompile) throws StandardException {
 		// Auto-generated method stub
 
 	}

Modified: db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java?rev=1574389&r1=1574388&r2=1574389&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java
(original)
+++ db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java
Wed Mar  5 07:57:03 2014
@@ -63,6 +63,7 @@ import org.apache.derbyTesting.junit.JDB
 import org.apache.derbyTesting.junit.TestConfiguration;
 //import org.apache.derby.shared.common.reference.JDBC40Translation;
 import org.apache.derbyTesting.functionTests.tests.upgradeTests.Version;
+import org.apache.derbyTesting.functionTests.util.Barrier;
 
 /**
  * Test the DatabaseMetaData api.
@@ -236,6 +237,11 @@ public class DatabaseMetaDataTest extend
             TestConfiguration.singleUseDatabaseDecorator(
                 new DatabaseMetaDataTest("initialCompilationTest")));
 
+        // The test for DERBY-4160 needs a fresh database to ensure that the
+        // meta-data queries haven't already been compiled.
+        suite.addTest(TestConfiguration.singleUseDatabaseDecorator(
+                new DatabaseMetaDataTest("concurrentCompilationTest")));
+
         // Test for DERBY-3693 needs a fresh database to ensure that the size
         // of SYSTABLES is so small that creating a relatively small number of
         // tables will cause the query plan for getTables() to be invalidated.
@@ -332,6 +338,66 @@ public class DatabaseMetaDataTest extend
     }
 
     /**
+     * Test that a meta-data query is compiled and stored correctly even when
+     * there's a lock conflict that causes the first attempt to store it to
+     * stop midway (DERBY-4160). This test needs a fresh database so that the
+     * meta-data calls are not already compiled.
+     */
+    public void concurrentCompilationTest() throws Exception {
+        // Create a barrier that can be used to synchronize the two threads
+        // so they perform the meta-data compilation at the same time.
+        final Barrier barrier = new Barrier(2);
+
+        // Create a thread thread that attempts to compile meta-data queries.
+        final DatabaseMetaData dmd = getDMD();
+        final Exception[] exception = new Exception[1];
+        Thread th = new Thread() {
+            public void run() {
+                try {
+                    concurrentCompilationTestHelper(barrier, dmd);
+                } catch (Exception e) {
+                    exception[0] = e;
+                }
+            }
+        };
+        th.start();
+
+        // At the same time, in the main thread, attempt to compile the same
+        // meta-data queries.
+        Connection c2 = openDefaultConnection();
+        concurrentCompilationTestHelper(barrier, c2.getMetaData());
+        c2.close();
+
+        // Wait until both threads are done.
+        th.join();
+
+        // Check if the helper thread got any exceptions.
+        if (exception[0] != null) {
+            fail("Exception in other thread", exception[0]);
+        }
+
+        // Finally, verify that the two meta-data methods used in the test
+        // are working.
+        testGetBestRowIdentifier();
+        testGetIndexInfo();
+    }
+
+    private void concurrentCompilationTestHelper(
+            Barrier barrier, DatabaseMetaData dmd) throws Exception {
+        // Wait until the other thread is ready to start, so that the
+        // compilation happens at the same time in both threads.
+        barrier.await();
+
+        // Often, but not always, the getIndexInfo() call would fail
+        // in one of the threads with the following error message:
+        // ERROR X0Y68: Column 'PARAM1' already exists.
+        ResultSet rs1 = dmd.getBestRowIdentifier(null, null, "", 0, true);
+        ResultSet rs2 = dmd.getIndexInfo(null, null, "", true, true);
+        JDBC.assertDrainResults(rs1);
+        JDBC.assertDrainResults(rs2);
+    }
+
+    /**
      * Tests that we don't get an internal timeout when a meta-data statement
      * is recompiled because the size of the tables it queries has changed
      * (DERBY-3693). The test must be run on a fresh database, to ensure that



Mime
View raw message