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/06/03 13:00:49 UTC

svn commit: r1130983 - in /db/derby/code/branches/10.8: ./ java/engine/org/apache/derby/iapi/services/io/ java/engine/org/apache/derby/iapi/types/ java/engine/org/apache/derby/impl/sql/compile/ java/engine/org/apache/derby/impl/sql/execute/ java/testin...

Author: kahatlen
Date: Fri Jun  3 11:00:48 2011
New Revision: 1130983

URL: http://svn.apache.org/viewvc?rev=1130983&view=rev
Log:
DERBY-3870: Concurrent Inserts of rows with XML data results in an exception

Merged from trunk (revisions 1101839, 1125305, 1126358 and 1127883).

Added:
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java
      - copied, changed from r1125305, db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java
    db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XMLConcurrencyTest.java
      - copied unchanged from r1101839, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XMLConcurrencyTest.java
Removed:
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
Modified:
    db/derby/code/branches/10.8/   (props changed)
    db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XML.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XMLDataValue.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
    db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
    db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java
    db/derby/code/branches/10.8/tools/jar/extraDBMSclasses.properties

Propchange: db/derby/code/branches/10.8/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jun  3 11:00:48 2011
@@ -1,2 +1,2 @@
 /db/derby/code/branches/10.7:1061570,1061578,1082235
-/db/derby/code/trunk:1063809,1088633,1091000,1091221,1091285,1092067,1092795,1094315,1094572,1094728,1096741,1096890,1097247,1097249,1097460,1097469,1097471,1102826,1103681,1103718,1127825,1129136,1129764,1129797
+/db/derby/code/trunk:1063809,1088633,1091000,1091221,1091285,1092067,1092795,1094315,1094572,1094728,1096741,1096890,1097247,1097249,1097460,1097469,1097471,1101839,1102826,1103681,1103718,1125305,1126358,1127825,1127883,1129136,1129764,1129797

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java Fri Jun  3 11:00:48 2011
@@ -525,7 +525,7 @@ String[] TwoByte = {
         /* 461 */   "org.apache.derby.impl.sql.catalog.CoreDDFinderClassInfo",
         /* 462 */   "org.apache.derby.impl.sql.catalog.CoreDDFinderClassInfo",
         /* 463 */   "org.apache.derby.impl.sql.catalog.CoreDDFinderClassInfo",
-        /* 464 */   "org.apache.derby.iapi.types.SqlXmlUtil",        
+        /* 464 */   null,
 		/* 465 */   "org.apache.derby.impl.store.raw.data.CompressSpacePageOperation",
         /* 466 */   "org.apache.derby.impl.store.access.btree.index.B2I_10_3",
         /* 467 */   "org.apache.derby.impl.store.access.heap.Heap",

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java Fri Jun  3 11:00:48 2011
@@ -506,12 +506,6 @@ public interface StoredFormatIds {
             (MIN_ID_2 + 456);
     
     /**
-        class org.apache.derby.iapi.types.SqlXmlUtil
-    */
-    static public final int SQL_XML_UTIL_V01_ID =
-            (MIN_ID_2 + 464);
-    
-    /**
         class org.apache.derby.iapi.types.JSQLType
      */
     static public final int JSQLTYPEIMPL_ID =

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java Fri Jun  3 11:00:48 2011
@@ -23,8 +23,6 @@ package org.apache.derby.iapi.types;
 
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.services.io.Formatable;
-import org.apache.derby.iapi.services.io.StoredFormatIds;
 import org.apache.derby.iapi.services.sanity.SanityManager;
 
 import java.util.Properties;
@@ -33,8 +31,6 @@ import java.util.Collections;
 import java.util.List;
 
 import java.io.IOException;
-import java.io.ObjectOutput;
-import java.io.ObjectInput;
 import java.io.StringReader;
 
 import java.lang.reflect.InvocationTargetException;
@@ -84,10 +80,8 @@ import javax.xml.transform.stream.Stream
  *       query expression a single time per statement, instead of
  *       having to do it for every row against which the query
  *       is evaluated.  An instance of this class is created at
- *       compile time and then passed (using "saved objects")
- *       to the appropriate operator implementation method in
- *       XML.java; see SqlXmlExecutor.java for more about the
- *       role this class plays in "saved object" processing.
+ *       compile time and then passed to the appropriate operator
+ *       implementation method in XML.java.
  *
  *    2. By keeping all XML-specific references in this one class, 
  *       we have a single "point of entry" to the XML objects--namely,
@@ -113,7 +107,7 @@ import javax.xml.transform.stream.Stream
  *       _if_ s/he is trying to access or operate on XML values.
  */
 
-public class SqlXmlUtil implements Formatable
+public class SqlXmlUtil
 {
     // Used to parse a string into an XML value (DOM); checks
     // the well-formedness of the string while parsing.
@@ -803,58 +797,6 @@ public class SqlXmlUtil implements Forma
         }
     }
 
-    /* ****
-     * Formatable interface implementation
-     * */
-
-    /** 
-     * @see java.io.Externalizable#writeExternal 
-     * 
-     * @exception IOException on error
-     */
-    public void writeExternal(ObjectOutput out) 
-        throws IOException
-    {
-        // query may be null
-        if (query == null)
-        {
-            out.writeBoolean(false);
-        }
-        else
-        {
-            out.writeBoolean(true);
-            out.writeObject(queryExpr);
-            out.writeObject(opName);
-        }
-    }
-
-    /** 
-     * @see java.io.Externalizable#readExternal 
-     *
-     * @exception IOException on error
-     * @exception ClassNotFoundException on error
-     */
-    public void readExternal(ObjectInput in) 
-        throws IOException, ClassNotFoundException
-    {
-        if (in.readBoolean())
-        {
-            queryExpr = (String)in.readObject();
-            opName = (String)in.readObject();
-            recompileQuery = true;
-	    }
-    }
-
-    /**
-     * Get the formatID which corresponds to this class.
-     *
-     * @return	the formatID of this class
-     */
-    public int getTypeFormatId()
-    { 
-        return StoredFormatIds.SQL_XML_UTIL_V01_ID;
-    }
-
     /*
      ** The XMLErrorHandler class is just a generic implementation
      ** of the ErrorHandler interface.  It allows us to catch

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XML.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XML.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XML.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XML.java Fri Jun  3 11:00:48 2011
@@ -598,7 +598,7 @@ public class XML
      * store the _serialized_ version locally and then return
      * this XMLDataValue.
      *
-     * @param text The string value to check.
+     * @param stringValue The string value to check.
      * @param preserveWS Whether or not to preserve
      *  ignorable whitespace.
      * @param sqlxUtil Contains SQL/XML objects and util
@@ -609,9 +609,18 @@ public class XML
      *  value is returned; otherwise, an exception is thrown. 
      * @exception StandardException Thrown on error.
      */
-    public XMLDataValue XMLParse(String text, boolean preserveWS,
-        SqlXmlUtil sqlxUtil) throws StandardException
+    public XMLDataValue XMLParse(
+            StringDataValue stringValue,
+            boolean preserveWS,
+            SqlXmlUtil sqlxUtil)
+        throws StandardException
     {
+        if (stringValue.isNull()) {
+            setToNull();
+            return this;
+        }
+
+        String text = stringValue.getString();
         try {
 
             if (preserveWS) {
@@ -834,10 +843,10 @@ public class XML
      * the received XMLDataValue "result" param (assuming "result" is
      * non-null; else create a new XMLDataValue).
      *
-     * @param result The result of a previous call to this method; null
-     *  if not called yet.
      * @param sqlxUtil Contains SQL/XML objects and util methods that
      *  facilitate execution of XML-related operations
+     * @param result The result of a previous call to this method; null
+     *  if not called yet.
      * @return An XMLDataValue whose content corresponds to the serialized
      *  version of the results from evaluation of the query expression.
      *  Note: this XMLDataValue may not be storable into Derby XML
@@ -845,8 +854,8 @@ public class XML
      * @exception Exception thrown on error (and turned into a
      *  StandardException by the caller).
      */
-    public XMLDataValue XMLQuery(XMLDataValue result,
-        SqlXmlUtil sqlxUtil) throws StandardException
+    public XMLDataValue XMLQuery(SqlXmlUtil sqlxUtil, XMLDataValue result)
+            throws StandardException
     {
         if (this.isNull()) {
         // if the context is null, we return null,

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XMLDataValue.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XMLDataValue.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XMLDataValue.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/XMLDataValue.java Fri Jun  3 11:00:48 2011
@@ -30,7 +30,7 @@ public interface XMLDataValue extends Da
      * store the _serialized_ version locally and then return
      * this XMLDataValue.
      *
-     * @param text The string value to check.
+     * @param stringValue The string value to check.
      * @param preserveWS Whether or not to preserve
      *  ignorable whitespace.
      * @param sqlxUtil Contains SQL/XML objects and util
@@ -41,8 +41,11 @@ public interface XMLDataValue extends Da
      *  value returned; otherwise, an exception is thrown. 
      * @exception StandardException Thrown on error.
      */
-	public XMLDataValue XMLParse(String text, boolean preserveWS,
-		SqlXmlUtil sqlxUtil) throws StandardException;
+    public XMLDataValue XMLParse(
+            StringDataValue stringValue,
+            boolean preserveWS,
+            SqlXmlUtil sqlxUtil)
+        throws StandardException;
 
     /**
      * The SQL/XML XMLSerialize operator.
@@ -90,10 +93,10 @@ public interface XMLDataValue extends Da
      * the received XMLDataValue "result" param (assuming "result" is
      * non-null; else create a new XMLDataValue).
      *
-     * @param result The result of a previous call to this method; null
-     *  if not called yet.
      * @param sqlxUtil Contains SQL/XML objects and util methods that
      *  facilitate execution of XML-related operations
+     * @param result The result of a previous call to this method; null
+     *  if not called yet.
      * @return An XMLDataValue whose content corresponds to the serialized
      *  version of the results from evaluation of the query expression.
      *  Note: this XMLDataValue may not be storable into Derby XML
@@ -101,7 +104,7 @@ public interface XMLDataValue extends Da
      * @exception Exception thrown on error (and turned into a
      *  StandardException by the caller).
      */
-    public XMLDataValue XMLQuery(XMLDataValue result, SqlXmlUtil sqlxUtil)
+    public XMLDataValue XMLQuery(SqlXmlUtil sqlxUtil, XMLDataValue result)
 		throws StandardException;
 
     /* ****

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java Fri Jun  3 11:00:48 2011
@@ -21,25 +21,16 @@
 
 package	org.apache.derby.impl.sql.compile;
 
-import org.apache.derby.iapi.sql.compile.Visitable;
 import org.apache.derby.iapi.sql.compile.Visitor;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
 import org.apache.derby.iapi.error.StandardException;
 
 import org.apache.derby.iapi.services.sanity.SanityManager;
 import org.apache.derby.iapi.services.compiler.MethodBuilder;
 import org.apache.derby.iapi.services.compiler.LocalField;
-import org.apache.derby.iapi.services.io.StoredFormatIds;
 
 import java.lang.reflect.Modifier;
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
-import org.apache.derby.iapi.types.StringDataValue;
 import org.apache.derby.iapi.types.TypeId;
 import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.SqlXmlUtil;
-
-import org.apache.derby.iapi.store.access.Qualifier;
 
 import org.apache.derby.iapi.reference.ClassName;
 import org.apache.derby.iapi.reference.JDBC40Translation;
@@ -48,7 +39,6 @@ import org.apache.derby.iapi.reference.S
 import org.apache.derby.iapi.util.JBitSet;
 import org.apache.derby.iapi.services.classfile.VMOpcode;
 
-import java.sql.Types;
 import java.util.Vector;
 
 /**
@@ -59,7 +49,7 @@ import java.util.Vector;
  *
  */
 
-public class BinaryOperatorNode extends ValueNode
+public class BinaryOperatorNode extends OperatorNode
 {
 	String	operator;
 	String	methodName;
@@ -125,9 +115,8 @@ public class BinaryOperatorNode extends 
 		{ClassName.StringDataValue, ClassName.XMLDataValue}		// XMLQuery
 	};
 
-	// Class used to compile an XML query expression and/or load/process
-	// XML-specific objects.
-	private SqlXmlUtil sqlxUtil;
+    /** The query expression if the operator is XMLEXISTS or XMLQUERY. */
+    private String xmlQuery;
 
 	/**
 	 * Initializer for a BinaryOperatorNode
@@ -352,11 +341,7 @@ public class BinaryOperatorNode extends 
                 SQLState.LANG_INVALID_XML_QUERY_EXPRESSION);
         }
         else {
-        // compile the query expression.
-            sqlxUtil = new SqlXmlUtil();
-            sqlxUtil.compileXQExpr(
-                ((CharConstantNode)leftOperand).getString(),
-                (operatorType == XMLEXISTS_OP ? "XMLEXISTS" : "XMLQUERY"));
+            xmlQuery = ((CharConstantNode)leftOperand).getString();
         }
 
         // Right operand must be an XML data value.  NOTE: This
@@ -498,29 +483,15 @@ public class BinaryOperatorNode extends 
 ** but how?
 */
 
+        // The number of arguments to pass to the method that implements the
+        // operator, depends on the type of the operator.
+        int numArgs;
+
 		// If we're dealing with XMLEXISTS or XMLQUERY, there is some
 		// additional work to be done.
 		boolean xmlGen =
 			(operatorType == XMLQUERY_OP) || (operatorType == XMLEXISTS_OP);
 
-		if (xmlGen) {
-		// We create an execution-time object so that we can retrieve
-		// saved objects (esp. our compiled query expression) from
-		// the activation.  We do this for two reasons: 1) this level
-		// of indirection allows us to separate the XML data type
-		// from the required XML implementation classes (esp. JAXP
-		// and Xalan classes)--for more on how this works, see the
-		// comments in SqlXmlUtil.java; and 2) we can take
-		// the XML query expression, which we've already compiled,
-		// and pass it to the execution-time object for each row,
-		// which means that we only have to compile the query
-		// expression once per SQL statement (instead of once per
-		// row); see SqlXmlExecutor.java for more.
-			mb.pushNewStart(
-				"org.apache.derby.impl.sql.execute.SqlXmlExecutor");
-			mb.pushNewComplete(addXmlOpMethodParams(acb, mb));
-		}
-
 		/*
 		** The receiver is the operand with the higher type precedence.
 		** Like always makes the left the receiver.
@@ -558,6 +529,9 @@ public class BinaryOperatorNode extends 
 			rightOperand.generateExpression(acb, mb);
 			mb.cast(rightInterfaceType); // second arg with cast
 			// stack: left, left, right
+
+            // We've pushed two arguments
+            numArgs = 2;
 		}
 		else
 		{
@@ -581,28 +555,33 @@ public class BinaryOperatorNode extends 
 			** UNLESS we're generating an XML operator such as XMLEXISTS.
 			** In that case we want to generate
 			** 
-			**  SqlXmlExecutor.method(left, right)"
-			**
-			** and we've already pushed the SqlXmlExecutor object to
-			** the stack.
+			**  <right expression>.method(sqlXmlUtil)
 			*/
 
 			rightOperand.generateExpression(acb, mb);			
 			mb.cast(receiverType); // cast the method instance
 			// stack: right
 			
-			if (!xmlGen) {
+            if (xmlGen) {
+                // Push one argument (the SqlXmlUtil instance)
+                numArgs = 1;
+                pushSqlXmlUtil(acb, mb, xmlQuery, operator);
+                // stack: right,sqlXmlUtil
+            } else {
+                // Push two arguments (left, right)
+                numArgs = 2;
+
 				mb.dup();
 				mb.cast(rightInterfaceType);
 				// stack: right,right
-			}
 			
-			leftOperand.generateExpression(acb, mb);
-			mb.cast(leftInterfaceType); // second arg with cast
-			// stack: right,right,left
-			
-			mb.swap();
-			// stack: right,left,right			
+                leftOperand.generateExpression(acb, mb);
+                mb.cast(leftInterfaceType); // second arg with cast
+                // stack: right,right,left
+
+                mb.swap();
+                // stack: right,left,right
+            }
 		}
 
 		/* Figure out the result type name */
@@ -610,15 +589,13 @@ public class BinaryOperatorNode extends 
 			? getTypeCompiler().interfaceName()
 			: resultInterfaceType;
 
-		// Boolean return types don't need a result field
-		boolean needField = !getTypeId().isBooleanTypeId();
-
-		if (needField) {
-
-			/* Allocate an object for re-use to hold the result of the operator */
-			LocalField resultField =
-				acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
+        // Boolean return types don't need a result field. For other types,
+        // allocate an object for re-use to hold the result of the operator.
+        LocalField resultField = getTypeId().isBooleanTypeId() ?
+            null : acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
 
+        // Push the result field onto the stack, if there is a result field.
+		if (resultField != null) {
 			/*
 			** Call the method for this operator.
 			*/
@@ -627,6 +604,9 @@ public class BinaryOperatorNode extends 
 			//before generating code "field = method(p1, p2, field);"
 			initializeResultField(acb, mb, resultField);
 
+            // Adjust number of arguments for the result field
+            numArgs++;
+
 			/* pass statically calculated scale to decimal divide method to make
 			 * result set scale consistent, beetle 3901
 			 */
@@ -637,17 +617,15 @@ public class BinaryOperatorNode extends 
 				operator.equals("/"))
 			{
 				mb.push(getTypeServices().getScale());		// 4th arg
-				mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 4);
-			}
-			else if (xmlGen) {
-			// This is for an XMLQUERY operation, so invoke the method
-			// on our execution-time object.
-				mb.callMethod(VMOpcode.INVOKEVIRTUAL, null,
-					methodName, resultTypeName, 3);
+                numArgs++;
 			}
-			else
-				mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 3);
+        }
+
+        mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType,
+                      methodName, resultTypeName, numArgs);
 
+        // Store the result of the method call, if there is a result field.
+        if (resultField != null) {
 			//the need for following if was realized while fixing bug 5704 where decimal*decimal was resulting an overflow value but we were not detecting it
 			if (getTypeId().variableLength())//since result type is numeric variable length, generate setWidth code.
 			{
@@ -670,17 +648,6 @@ public class BinaryOperatorNode extends 
 			*/
 
 			mb.putField(resultField);
-		} else {
-			if (xmlGen) {
-			// This is for an XMLEXISTS operation, so invoke the method
-			// on our execution-time object.
-				mb.callMethod(VMOpcode.INVOKEVIRTUAL, null,
-					methodName, resultTypeName, 2);
-			}
-			else {
-				mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType,
-					methodName, resultTypeName, 2);
-			}
 		}
 	}
 
@@ -875,32 +842,4 @@ public class BinaryOperatorNode extends 
         	       && leftOperand.isEquivalent(other.leftOperand)
         	       && rightOperand.isEquivalent(other.rightOperand);
         }
-
-	/**
-	 * Push the fields necessary to generate an instance of
-	 * SqlXmlExecutor, which will then be used at execution
-	 * time to retrieve the compiled XML query expression,
-	 * along with any other XML-specific objects.
-	 *
-	 * @param acb The ExpressionClassBuilder for the class we're generating
-	 * @param mb  The method the code to place the code
-	 *
-	 * @return The number of items that this method pushed onto
-	 *  the mb's stack.
-	 */
-	private int addXmlOpMethodParams(ExpressionClassBuilder acb,
-		MethodBuilder mb) throws StandardException
-	{
-		// Push activation so that we can get our saved object
-		// (which will hold the compiled XML query expression)
-		// back at execute time.
-		acb.pushThisAsActivation(mb);
-
-		// Push our saved object (the compiled query and XML-specific
-		// objects).
-		mb.push(getCompilerContext().addSavedObject(sqlxUtil));
-
-		// We pushed 2 items to the stack.
-		return 2;
-	}
 }

Copied: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java (from r1125305, db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java)
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java?p2=db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java&p1=db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java&r1=1125305&r2=1130983&rev=1130983&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java Fri Jun  3 11:00:48 2011
@@ -36,9 +36,8 @@ abstract class OperatorNode extends Valu
     /**
      * <p>
      * Generate code that pushes an SqlXmlUtil instance onto the stack. The
-     * instance will be created and cached in the activation the first time
-     * the code is executed, so that we don't need to create a new instance
-     * for every row.
+     * instance will be created and cached in the activation's constructor, so
+     * that we don't need to create a new instance for every row.
      * </p>
      *
      * <p>
@@ -59,37 +58,31 @@ abstract class OperatorNode extends Valu
 
         // Create a field in which the instance can be cached.
         LocalField sqlXmlUtil = acb.newFieldDeclaration(
-                Modifier.PRIVATE, SqlXmlUtil.class.getName());
+                Modifier.PRIVATE | Modifier.FINAL, SqlXmlUtil.class.getName());
 
-        // Read the cached value.
-        mb.getField(sqlXmlUtil);
-
-        // Check if the cached value is null. If it is, create a new instance.
-        // Otherwise, we're happy with the stack as it is (the cached instance
-        // will be on top of it), and nothing more is needed.
-        mb.dup();
-        mb.conditionalIfNull();
-
-        // The cached value is null. Pop it from the stack so that we can put
-        // a fresh instance there in its place.
-        mb.pop();
-
-        // Create a new instance and cache it in the field. Its value will be
-        // on the top of the stack after this sequence.
-        mb.pushNewStart(SqlXmlUtil.class.getName());
-        mb.pushNewComplete(0);
-        mb.putField(sqlXmlUtil);
-
-        // If a query is specified, compile it.
-        if (xmlQuery != null) {
-            mb.dup();
-            mb.push(xmlQuery);
-            mb.push(xmlOpName);
-            mb.callMethod(
+        // Add code that creates the SqlXmlUtil instance in the constructor.
+        MethodBuilder constructor = acb.getConstructor();
+        constructor.pushNewStart(SqlXmlUtil.class.getName());
+        constructor.pushNewComplete(0);
+        constructor.putField(sqlXmlUtil);
+
+        // Compile the query, if one is specified.
+        if (xmlQuery == null) {
+            // No query. The SqlXmlUtil instance is still on the stack. Pop it
+            // to restore the initial state of the stack.
+            constructor.pop();
+        } else {
+            // Compile the query. This will consume the SqlXmlUtil instance
+            // and leave the stack in its initial state.
+            constructor.push(xmlQuery);
+            constructor.push(xmlOpName);
+            constructor.callMethod(
                     VMOpcode.INVOKEVIRTUAL, SqlXmlUtil.class.getName(),
                     "compileXQExpr", "void", 2);
         }
 
-        mb.completeConditional();
+        // Read the cached value and push it onto the stack in the method
+        // generated for the operator.
+        mb.getField(sqlXmlUtil);
     }
 }

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java Fri Jun  3 11:00:48 2011
@@ -54,7 +54,7 @@ import java.util.Vector;
  *
  */
 
-public class TernaryOperatorNode extends ValueNode
+public class TernaryOperatorNode extends OperatorNode
 {
 	String		operator;
 	String		methodName;

Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java Fri Jun  3 11:00:48 2011
@@ -23,11 +23,8 @@ package	org.apache.derby.impl.sql.compil
 
 import org.apache.derby.iapi.store.access.Qualifier;
 
-import org.apache.derby.iapi.sql.compile.Visitable;
 import org.apache.derby.iapi.sql.compile.Visitor;
 
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-
 import org.apache.derby.iapi.reference.JDBC40Translation;
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.reference.ClassName;
@@ -35,15 +32,11 @@ import org.apache.derby.iapi.error.Stand
 import org.apache.derby.iapi.services.sanity.SanityManager;
 import org.apache.derby.iapi.services.compiler.MethodBuilder;
 import org.apache.derby.iapi.services.compiler.LocalField;
-import org.apache.derby.iapi.services.io.StoredFormatIds;
 
-import org.apache.derby.iapi.types.StringDataValue;
 import org.apache.derby.iapi.types.TypeId;
 import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.SqlXmlUtil;
 
 import java.lang.reflect.Modifier;
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
 
 import org.apache.derby.iapi.util.JBitSet;
 import org.apache.derby.iapi.services.classfile.VMOpcode;
@@ -59,7 +52,7 @@ import java.util.Vector;
  *
  */
 
-public class UnaryOperatorNode extends ValueNode
+public class UnaryOperatorNode extends OperatorNode
 {
 	String	operator;
 	String	methodName;
@@ -121,10 +114,6 @@ public class UnaryOperatorNode extends V
 	// args required by the operator method call.
 	private Object [] additionalArgs;
 
-	// Class used to hold XML-specific objects required for
-	// parsing/serializing XML data.
-	private SqlXmlUtil sqlxUtil;
-
 	/**
 	 * Initializer for a UnaryOperatorNode.
 	 *
@@ -383,12 +372,6 @@ public class UnaryOperatorNode extends V
             }
         }
 
-        // Create a new XML compiler object; the constructor
-        // here automatically creates the XML-specific objects 
-        // required for parsing/serializing XML, so all we
-        // have to do is create an instance.
-        sqlxUtil = new SqlXmlUtil();
-
         // The result type of XMLParse() is always an XML type.
         setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor(
                 JDBC40Translation.SQLXML));
@@ -624,26 +607,6 @@ public class UnaryOperatorNode extends V
 											MethodBuilder mb)
 									throws StandardException
 	{
-		// For XML operator we do some extra work.
-		boolean xmlGen = (operatorType == XMLPARSE_OP) ||
-			(operatorType == XMLSERIALIZE_OP);
-
-		if (xmlGen) {
-		// We create an execution-time object from which we call
-		// the necessary methods.  We do this for two reasons: 1) this
-		// level of indirection allows us to separate the XML data type
-		// from the required XML implementation classes (esp. JAXP and
-		// Xalan classes)--for more on how this works, see the comments
-		// in SqlXmlUtil.java; and 2) this allows us to create the
-		// required XML objects a single time (which we did at bind time
-		// when we created a new SqlXmlUtil) and then reuse those objects
-		// for each row in the target result set, instead of creating
-		// new objects every time; see SqlXmlUtil.java for more.
-			mb.pushNewStart(
-				"org.apache.derby.impl.sql.execute.SqlXmlExecutor");
-			mb.pushNewComplete(addXmlOpMethodParams(acb, mb));
-		}
-
 		String resultTypeName = 
 			(operatorType == -1)
 				? getTypeCompiler().interfaceName()
@@ -664,25 +627,13 @@ public class UnaryOperatorNode extends V
 			LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
 			mb.getField(field);
 
-			/* If we're calling a method on a class (SqlXmlExecutor) instead
-			 * of calling a method on the operand interface, then we invoke
-			 * VIRTUAL; we then have 2 args (the operand and the local field)
-			 * instead of one, i.e:
-			 *
-			 *  SqlXmlExecutor.method(operand, field)
-			 *
-			 * instead of
-			 *
-			 *  <operand>.method(field).
-			 */
-			if (xmlGen) {
-				mb.callMethod(VMOpcode.INVOKEVIRTUAL, null,
-					methodName, resultTypeName, 2);
-			}
-			else {
-				mb.callMethod(VMOpcode.INVOKEINTERFACE,
-					(String) null, methodName, resultTypeName, 1);
-			}
+            int numArgs = 1;
+
+            // XML operators take extra arguments.
+            numArgs += addXmlOpMethodParams(acb, mb, field);
+
+            mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+                          methodName, resultTypeName, numArgs);
 
 			/*
 			** Store the result of the method call in the field, so we can re-use
@@ -763,11 +714,14 @@ public class UnaryOperatorNode extends V
     /**
      * Add some additional arguments to our method call for
      * XML related operations like XMLPARSE and XMLSERIALIZE.
+     *
+     * @param acb the builder for the class in which the method lives
      * @param mb The MethodBuilder that will make the call.
+     * @param resultField the field that contains the previous result
      * @return Number of parameters added.
      */
     protected int addXmlOpMethodParams(ExpressionClassBuilder acb,
-		MethodBuilder mb) throws StandardException
+		MethodBuilder mb, LocalField resultField) throws StandardException
     {
         if ((operatorType != XMLPARSE_OP) && (operatorType != XMLSERIALIZE_OP))
         // nothing to do.
@@ -798,20 +752,26 @@ public class UnaryOperatorNode extends V
 
         /* Else we're here for XMLPARSE. */
 
-        // Push activation, which we use at execution time to
-        // get our saved object (which will hold objects used
-        // for parsing/serializing) back.
-        acb.pushThisAsActivation(mb);
-
-        // Push our XML object (used for parsing/serializing) as
-        // a saved object, so that we can retrieve it at execution
-        // time.  This allows us to avoid having to re-create the
-        // objects for every row in a given result set.
-        mb.push(getCompilerContext().addSavedObject(sqlxUtil));
+        // XMLPARSE is different from other unary operators in that the method
+        // must be called on the result object (the XML value) and not on the
+        // operand (the string value). We must therefore make sure the result
+        // object is not null.
+        MethodBuilder constructor = acb.getConstructor();
+        acb.generateNull(constructor, getTypeCompiler(),
+                         getTypeServices().getCollationType());
+        constructor.setField(resultField);
+
+        // Swap operand and result object so that the method will be called
+        // on the result object.
+        mb.swap();
 
         // Push whether or not we want to preserve whitespace.
         mb.push(((Boolean)additionalArgs[0]).booleanValue());
-        return 3;
+
+        // Push the SqlXmlUtil instance as the next argument.
+        pushSqlXmlUtil(acb, mb, null, null);
+
+        return 2;
     }
     
     /**

Modified: db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java Fri Jun  3 11:00:48 2011
@@ -50,6 +50,7 @@ public final class XMLSuite extends Base
         suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLTypeAndOpsTest.suite());
         suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLBindingTest.suite());
         suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLMissingClassesTest.suite());
+        suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLConcurrencyTest.suite());
         
         return suite;
     }

Modified: db/derby/code/branches/10.8/tools/jar/extraDBMSclasses.properties
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/tools/jar/extraDBMSclasses.properties?rev=1130983&r1=1130982&r2=1130983&view=diff
==============================================================================
--- db/derby/code/branches/10.8/tools/jar/extraDBMSclasses.properties (original)
+++ db/derby/code/branches/10.8/tools/jar/extraDBMSclasses.properties Fri Jun  3 11:00:48 2011
@@ -99,7 +99,5 @@ derby.module.store.jardbf=org.apache.der
 derby.module.store.urlf=org.apache.derby.impl.io.URLFile
 derby.module.store.cpf=org.apache.derby.impl.io.CPFile
 
-derby.module.xml.sqlxmle=org.apache.derby.impl.sql.execute.SqlXmlExecutor
-
 derby.module.shared.threaddump=org.apache.derby.shared.common.sanity.ThreadDump
 derby.module.engine.threaddump=org.apache.derby.iapi.error.ThreadDump