db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1125305 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/services/io/ engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/funct...
Date Fri, 20 May 2011 09:59:45 GMT
Author: kahatlen
Date: Fri May 20 09:59:44 2011
New Revision: 1125305

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

Store XML utility instance in the activation instead of in the
compiled plan, so that it's never accessed concurrently by multiple
threads.

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java  
(with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
Fri May 20 09:59:44 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/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
Fri May 20 09:59:44 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/trunk/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java Fri May 20
09:59:44 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;
@@ -113,7 +109,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 +799,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/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
Fri May 20 09:59:44 2011
@@ -21,26 +21,18 @@
 
 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;
 import org.apache.derby.iapi.reference.SQLState;
@@ -48,7 +40,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 +50,7 @@ import java.util.Vector;
  *
  */
 
-public class BinaryOperatorNode extends ValueNode
+public class BinaryOperatorNode extends OperatorNode
 {
 	String	operator;
 	String	methodName;
@@ -125,9 +116,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 +342,13 @@ 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();
+
+            // Compile the query expression. The compiled query will not be
+            // used, as each activation will need to compile its own version.
+            // But we still do this here to get a compile-time error in case
+            // the query expression has syntax errors.
+            new SqlXmlUtil().compileXQExpr(xmlQuery, operator);
         }
 
         // Right operand must be an XML data value.  NOTE: This
@@ -518,7 +510,8 @@ public class BinaryOperatorNode extends 
 		// row); see SqlXmlExecutor.java for more.
 			mb.pushNewStart(
 				"org.apache.derby.impl.sql.execute.SqlXmlExecutor");
-			mb.pushNewComplete(addXmlOpMethodParams(acb, mb));
+            pushSqlXmlUtil(acb, mb, xmlQuery, operator);
+            mb.pushNewComplete(1);
 		}
 
 		/*
@@ -875,32 +868,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;
-	}
 }

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java?rev=1125305&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java Fri
May 20 09:59:44 2011
@@ -0,0 +1,95 @@
+/*
+
+   Derby - Class org.apache.derby.impl.sql.compile.OperatorNode
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import java.lang.reflect.Modifier;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+import org.apache.derby.iapi.services.compiler.LocalField;
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.types.SqlXmlUtil;
+
+/**
+ * Abstract base-class for the various operator nodes: UnaryOperatorNode,
+ * BinaryOperatorNode and TernarnyOperatorNode.
+ */
+abstract class OperatorNode extends ValueNode {
+
+    /**
+     * <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.
+     * </p>
+     *
+     * <p>
+     * If the {@code xmlQuery} parameter is non-null, there will also be code
+     * that compiles the query when the SqlXmlUtil instance is created.
+     * </p>
+     *
+     * @param acb builder for the class in which the generated code lives
+     * @param mb builder for the method that implements this operator
+     * @param xmlQuery the XML query to be executed by the operator, or
+     * {@code null} if this isn't an XMLEXISTS or XMLQUERY operator
+     * @param xmlOpName the name of the operator (ignored if {@code xmlQuery}
+     * is {@code null})
+     */
+    static void pushSqlXmlUtil(
+            ExpressionClassBuilder acb, MethodBuilder mb,
+            String xmlQuery, String xmlOpName) {
+
+        // Create a field in which the instance can be cached.
+        LocalField sqlXmlUtil = acb.newFieldDeclaration(
+                Modifier.PRIVATE, 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(
+                    VMOpcode.INVOKEVIRTUAL, SqlXmlUtil.class.getName(),
+                    "compileXQExpr", "void", 2);
+        }
+
+        mb.completeConditional();
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OperatorNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
Fri May 20 09:59:44 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/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
Fri May 20 09:59:44 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));
@@ -798,20 +781,12 @@ 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));
+        // Push the SqlXmlUtil instance as the first argument.
+        pushSqlXmlUtil(acb, mb, null, null);
 
         // Push whether or not we want to preserve whitespace.
         mb.push(((Boolean)additionalArgs[0]).booleanValue());
-        return 3;
+        return 2;
     }
     
     /**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
Fri May 20 09:59:44 2011
@@ -22,8 +22,6 @@
 package org.apache.derby.impl.sql.execute;
 
 import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.sql.Activation;
 
 import org.apache.derby.iapi.types.BooleanDataValue;
 import org.apache.derby.iapi.types.StringDataValue;
@@ -32,6 +30,7 @@ import org.apache.derby.iapi.types.XMLDa
 import org.apache.derby.iapi.types.SqlXmlUtil;
 
 /**
+ * <p>
  * This class is really just an execution time "utility" that
  * makes calls to methods on the XMLDataValue interface.  Instances
  * of this class are generated at execution time by the various
@@ -40,33 +39,38 @@ import org.apache.derby.iapi.types.SqlXm
  * that instance (see, for example, the generateExpression() methods
  * in UnaryOperatorNode and BinaryOperatorNode).  When an instance
  * of this class is instantiated, one of the arguments that can be
- * provided is an id that is used to retrieve an already-constructed
- * (from compilation time) instance of SqlXmlUtil from the current
+ * provided is an already-constructed instance of SqlXmlUtil from the current
  * Activation.  When it comes time to execute the operator, this class
  * just makes the appropriate call on the received XMLDataValue object
  * and passes in the SqlXmlUtil, from which the XMLDataValue can
  * retrieve compile-time objects.  The XMLDataValue can also make
  * calls to various XML-specific utilities on the SqlXmlUtil
  * object.
+ * </p>
  *
+ * <p>
  * Let's take an example.  Assume the statement that the user
  * wants to execute is:
+ * </p>
  *
+ * <pre>
  *   select id from xtable
  *      where XMLEXISTS('/simple' PASSING BY REF xcol)
+ * </pre>
  *
- * At compilation time we will compile the expression "/simple"
- * and store the compiled version of the query into an instance
- * of SqlXmlUtil.  Then we will save that instance of SqlXmlUtil
- * as an object in the statement activation, from which we will
- * receive an id that can be used later to retrieve the object
- * (i.e. to retrieve the SqlXmlUtil).  Then, for *each* row
- * in xtable, we'll generate the following:
+ * <p>
+ * For each activation of the statement, the first time a row is read from
+ * xtable, the expression "/simple" is compiled and stored in the activation.
+ * Then, for each row in xtable, we'll generate the following:
+ * </p>
  *
+ * <pre>
  *  boolean result =
- *    (new SqlXmlExecutor(activation, compileTimeObjectId)).
+ *    (new SqlXmlExecutor(cachedSqlXmlUtilInstance)).
  *      XMLExists("/simple", xcol);
+ * </pre>
  *
+ * <p>
  * In other words, for each row we create a new instance of
  * this class and call "XMLExists" on that instance.  Then,
  * as seen below, we retrieve the SqlXmlUtil from the activation
@@ -75,7 +79,9 @@ import org.apache.derby.iapi.types.SqlXm
  * methods and objects (which include the compiled query
  * expression for "/simple") defined on SqlXmlUtil to complete
  * the operation.
- * 
+ * </p>
+ *
+ * <p>
  * Okay, so why do we use this execution-time SqlXmlExecutor class
  * instead of just generating a call to XMLDataValue.XMLExists()
  * directly?  The reason is that we only want to compile the XML
@@ -88,22 +94,32 @@ import org.apache.derby.iapi.types.SqlXm
  * and then pass the compiled object into XMLDataValue--in either
  * case, we'd end up compiling the XML query expression (and creating
  * the corresponding XML-specific objects) once for each row in
- * the target result set.  By using the "saveObject" functionality
- * in Activation along with this SqlXmlExecutor class, we make
+ * the target result set.  By caching the SqlXmlUtil instance in the
+ * Activation and access it via this SqlXmlExecutor class, we make
  * it so that we only have to compile the XML query expression and
- * create XML-specific objects once (at compile time), and then
+ * create XML-specific objects once per activation, and then
  * we can re-use those objects for every row in the target
  * result set.  Yes, we're still creating an instance of this
- * class (SqlXmlExecutor) once per row, and yes we have to fetch
- * the appropriate SqlXmlUtil object once per row, but this is
+ * class (SqlXmlExecutor) once per row, but this is
  * still going to be cheaper than having to re-compile the query
  * expression and re-create XML objects for every row.
- * 
+ * </p>
+ *
+ * <p>
  * So in short, this class allows us to improve the execution-time
  * performance of XML operators by allowing us to create XML-
  * specific objects and compile XML query expressions once per
  * statement, instead of once per row.
+ * </p>
+ *
+ * <p>
+ * The next paragraph contains a historical note about why this class is
+ * placed in this package. It is no longer true that the class uses the
+ * {@code getSavedObject()} method on the Activation, so it should now be
+ * safe to move it to the types package.
+ * </p>
  *
+ * <p><i>
  * One final note: the reason this class is in this package
  * instead of the types package is that, in order to retrieve
  * the compile-time objects, we have to use the "getSavedObject()"
@@ -116,15 +132,13 @@ import org.apache.derby.iapi.types.SqlXm
  * the execution package seems more appropriate since this
  * class is only instantiated and used during execution, not
  * during compilation.
+ * </i></p>
  */
 
 public class SqlXmlExecutor {
 
-    // The activation from which we load the compile-time XML
-    // objects (including the compiled XML query expression in
-    // case of XMLEXISTS and XMLQUERY).
-    private Activation activation;
-    private int sqlXUtilId;
+    /** Utility instance that performs the actual XML operations. */
+    private final SqlXmlUtil sqlXmlUtil;
 
     // Target type, target width and target collation type that 
     // were specified for an XMLSERIALIZE operator.
@@ -138,15 +152,12 @@ public class SqlXmlExecutor {
 
     /**
      * Constructor 1: Used for XMLPARSE op.
-     * @param activation Activation from which to retrieve saved objects
-     * @param utilId Id by which we find saved objects in activation
+     * @param sqlXmlUtil utility that performs the parsing
      * @param preserveWS Whether or not to preserve whitespace
      */
-    public SqlXmlExecutor(Activation activation, int utilId,
-        boolean preserveWS)
+    public SqlXmlExecutor(SqlXmlUtil sqlXmlUtil, boolean preserveWS)
     {
-        this.activation = activation;
-        this.sqlXUtilId = utilId;
+        this.sqlXmlUtil = sqlXmlUtil;
         this.preserveWS = preserveWS;
     }
 
@@ -159,6 +170,7 @@ public class SqlXmlExecutor {
     public SqlXmlExecutor(int targetTypeId, int targetMaxWidth, 
     		int targetCollationType)
     {
+        this.sqlXmlUtil = null;
         this.targetTypeId = targetTypeId;
         this.targetMaxWidth = targetMaxWidth;
         this.targetCollationType = targetCollationType;
@@ -166,13 +178,11 @@ public class SqlXmlExecutor {
 
     /**
      * Constructor 3: Used for XMLEXISTS/XMLQUERY ops.
-     * @param activation Activation from which to retrieve saved objects
-     * @param utilId Id by which we find saved objects in activation
+     * @param sqlXmlUtil utility that performs the query
      */
-    public SqlXmlExecutor(Activation activation, int utilId)
+    public SqlXmlExecutor(SqlXmlUtil sqlXmlUtil)
     {
-        this.activation = activation;
-        this.sqlXUtilId = utilId;
+        this.sqlXmlUtil = sqlXmlUtil;
     }
 
     /**
@@ -201,7 +211,7 @@ public class SqlXmlExecutor {
         }
 
         return result.XMLParse(
-            xmlText.getString(), preserveWS, getSqlXmlUtil());
+            xmlText.getString(), preserveWS, sqlXmlUtil);
     }
 
     /**
@@ -235,7 +245,7 @@ public class SqlXmlExecutor {
     public BooleanDataValue XMLExists(StringDataValue xExpr,
         XMLDataValue xmlContext) throws StandardException
     {
-        return xmlContext.XMLExists(getSqlXmlUtil());
+        return xmlContext.XMLExists(sqlXmlUtil);
     }
 
     /**
@@ -249,7 +259,7 @@ public class SqlXmlExecutor {
      *  the expression.
      * @param result XMLDataValue in which to store the result
      * @return The received XMLDataValue with its content set to
-     *  result of evaulating the query expression against xmlContext.
+     *  result of evaluating the query expression against xmlContext.
      *  If the received XMLDataValue is null, then create a new one
      *  and set its content to correspond to the received xmlText.
      */
@@ -257,19 +267,6 @@ public class SqlXmlExecutor {
         XMLDataValue xmlContext, XMLDataValue result)
         throws StandardException
     {
-        return xmlContext.XMLQuery(result, getSqlXmlUtil());
-    }
-
-    /**
-     * Return the saved object in this.activation that corresponds to
-     * this.sqlxUtilId.  Assumption is that those fields have been
-     * set by the time we get here.
-     */
-    private SqlXmlUtil getSqlXmlUtil()
-        throws StandardException
-    {
-        return (SqlXmlUtil)
-            activation.getPreparedStatement().getSavedObject(sqlXUtilId);
+        return xmlContext.XMLQuery(result, sqlXmlUtil);
     }
-
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java?rev=1125305&r1=1125304&r2=1125305&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/XMLSuite.java
Fri May 20 09:59:44 2011
@@ -50,8 +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());
-        // XMLConcurrencyTest is disabled until DERBY-3870 is fixed.
-        // suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLConcurrencyTest.suite());
+        suite.addTest(org.apache.derbyTesting.functionTests.tests.lang.XMLConcurrencyTest.suite());
         
         return suite;
     }



Mime
View raw message