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 ka...@apache.org on 2011/10/28 11:29:14 UTC

svn commit: r1190220 - in /db/derby/code/trunk/java/engine/org/apache/derby/impl/sql: GenericPreparedStatement.java GenericStatement.java

Author: kahatlen
Date: Fri Oct 28 09:29:14 2011
New Revision: 1190220

URL: http://svn.apache.org/viewvc?rev=1190220&view=rev
Log:
DERBY-5406: Intermittent failures in CompressTableTest and TruncateTableTest

Push retry logic down to GenericStatement.prepare() so that it also
covers the code path from Connection.prepareStatement(). The previous
location only covered compilations requested by the execute methods.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java?rev=1190220&r1=1190219&r2=1190220&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java Fri Oct 28 09:29:14 2011
@@ -148,7 +148,7 @@ public class GenericPreparedStatement
 	boolean compilingStatement;
 
     /** True if the statement was invalidated while it was being compiled. */
-    private boolean invalidatedWhileCompiling;
+    boolean invalidatedWhileCompiling;
 
 	////////////////////////////////////////////////
 	// STATE that is not copied by getClone()
@@ -408,47 +408,7 @@ recompileOutOfDatePlan:
 			// to execute.  That exception will be caught by the executeSPS()
 			// method of the GenericTriggerExecutor class, and at that time
 			// the SPS action will be recompiled correctly.
-
-                final int depth = lccToUse.getStatementDepth();
-                try {
-                    rePrepare(lccToUse);
-                } finally {
-                    boolean recompile = false;
-
-                    // Check if the statement was invalidated while it was
-                    // compiled. If so, the newly compiled plan may or may
-                    // not be up to date anymore, so we recompile the statement
-                    // if this happens. Note that this is checked in a finally
-                    // block, so we also retry if an exception was thrown. The
-                    // exception was probably thrown because of the changes
-                    // that invalidated the statement. If not, recompiling
-                    // will also fail, and the exception will be exposed to
-                    // the caller.
-                    //
-                    // invalidatedWhileCompiling and isValid are protected by
-                    // synchronization on "this".
-                    synchronized (this) {
-                        if (invalidatedWhileCompiling) {
-                            isValid = false;
-                            invalidatedWhileCompiling = false;
-                            recompile = true;
-                        }
-                    }
-
-                    if (recompile) {
-                        // A new statement context is pushed while compiling.
-                        // Typically, this context is popped by an error
-                        // handler at a higher level. But since we retry the
-                        // compilation, the error handler won't be invoked, so
-                        // the stack must be reset to its original state first.
-                        while (lccToUse.getStatementDepth() > depth) {
-                            lccToUse.popStatementContext(
-                                    lccToUse.getStatementContext(), null);
-                        }
-
-                        continue recompileOutOfDatePlan;
-                    }
-                }
+                rePrepare(lccToUse);
 			}
 
 			StatementContext statementContext = lccToUse.pushStatementContext(

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java?rev=1190220&r1=1190219&r2=1190220&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java Fri Oct 28 09:29:14 2011
@@ -82,7 +82,7 @@ public class GenericStatement
 		** Note: don't reset state since this might be
 		** a recompilation of an already prepared statement.
 		*/ 
-		return prepMinion(lcc, true, (Object[]) null, (SchemaDescriptor) null, false); 
+		return prepare(lcc, false);
 	}
 	public PreparedStatement prepare(LanguageConnectionContext lcc, boolean forMetaData) throws StandardException
 	{
@@ -90,7 +90,52 @@ public class GenericStatement
 		** Note: don't reset state since this might be
 		** a recompilation of an already prepared statement.
 		*/ 
-		return prepMinion(lcc, true, (Object[]) null, (SchemaDescriptor) null, forMetaData); 
+
+        final int depth = lcc.getStatementDepth();
+        while (true) {
+            try {
+                return prepMinion(lcc, true, (Object[]) null,
+                                  (SchemaDescriptor) null, forMetaData);
+            } finally {
+                boolean recompile = false;
+
+                // Check if the statement was invalidated while it was
+                // compiled. If so, the newly compiled plan may not be
+                // up to date anymore, so we recompile the statement
+                // if this happens. Note that this is checked in a finally
+                // block, so we also retry if an exception was thrown. The
+                // exception was probably thrown because of the changes
+                // that invalidated the statement. If not, recompiling
+                // will also fail, and the exception will be exposed to
+                // the caller.
+                //
+                // invalidatedWhileCompiling and isValid are protected by
+                // synchronization on the prepared statement.
+                synchronized (preparedStmt) {
+                    if (preparedStmt.invalidatedWhileCompiling) {
+                        preparedStmt.isValid = false;
+                        preparedStmt.invalidatedWhileCompiling = false;
+                        recompile = true;
+                    }
+                }
+
+                if (recompile) {
+                    // A new statement context is pushed while compiling.
+                    // Typically, this context is popped by an error
+                    // handler at a higher level. But since we retry the
+                    // compilation, the error handler won't be invoked, so
+                    // the stack must be reset to its original state first.
+                    while (lcc.getStatementDepth() > depth) {
+                        lcc.popStatementContext(
+                                lcc.getStatementContext(), null);
+                    }
+
+                    // Don't return yet. The statement was invalidated, so
+                    // we must retry the compilation.
+                    continue;
+                }
+            }
+        }
 	}
 
 	private PreparedStatement prepMinion(LanguageConnectionContext lcc, boolean cacheMe, Object[] paramDefaults,