Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E69686BD7 for ; Fri, 3 Jun 2011 11:01:17 +0000 (UTC) Received: (qmail 98202 invoked by uid 500); 3 Jun 2011 11:01:17 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 98175 invoked by uid 500); 3 Jun 2011 11:01:17 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 98168 invoked by uid 99); 3 Jun 2011 11:01:17 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jun 2011 11:01:17 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 Jun 2011 11:01:11 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 9D0CC2388A19; Fri, 3 Jun 2011 11:00:49 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Fri, 03 Jun 2011 11:00:49 -0000 To: derby-commits@db.apache.org From: kahatlen@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110603110049.9D0CC2388A19@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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. + ** .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 /** *

* 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. *

* *

@@ -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 - * - * .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