Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / execute / SqlXmlExecutor.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/execute/SqlXmlExecutor.java
new file mode 100644 (file)
index 0000000..5100361
--- /dev/null
@@ -0,0 +1,275 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.execute.SqlXmlExecutor\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.execute;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.sql.Activation;\r
+\r
+import org.apache.derby.iapi.types.BooleanDataValue;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+import org.apache.derby.iapi.types.XML;\r
+import org.apache.derby.iapi.types.XMLDataValue;\r
+import org.apache.derby.iapi.types.SqlXmlUtil;\r
+\r
+/**\r
+ * This class is really just an execution time "utility" that\r
+ * makes calls to methods on the XMLDataValue interface.  Instances\r
+ * of this class are generated at execution time by the various\r
+ * Derby XML operators--one instance for each row in the target\r
+ * result set--and then the appropriate operator call is made on\r
+ * that instance (see, for example, the generateExpression() methods\r
+ * in UnaryOperatorNode and BinaryOperatorNode).  When an instance\r
+ * of this class is instantiated, one of the arguments that can be\r
+ * provided is an id that is used to retrieve an already-constructed\r
+ * (from compilation time) instance of SqlXmlUtil from the current\r
+ * Activation.  When it comes time to execute the operator, this class\r
+ * just makes the appropriate call on the received XMLDataValue object\r
+ * and passes in the SqlXmlUtil, from which the XMLDataValue can\r
+ * retrieve compile-time objects.  The XMLDataValue can also make\r
+ * calls to various XML-specific utilities on the SqlXmlUtil\r
+ * object.\r
+ *\r
+ * Let's take an example.  Assume the statement that the user\r
+ * wants to execute is:\r
+ *\r
+ *   select id from xtable\r
+ *      where XMLEXISTS('/simple' PASSING BY REF xcol)\r
+ *\r
+ * At compilation time we will compile the expression "/simple"\r
+ * and store the compiled version of the query into an instance\r
+ * of SqlXmlUtil.  Then we will save that instance of SqlXmlUtil\r
+ * as an object in the statement activation, from which we will\r
+ * receive an id that can be used later to retrieve the object\r
+ * (i.e. to retrieve the SqlXmlUtil).  Then, for *each* row\r
+ * in xtable, we'll generate the following:\r
+ *\r
+ *  boolean result =\r
+ *    (new SqlXmlExecutor(activation, compileTimeObjectId)).\r
+ *      XMLExists("/simple", xcol);\r
+ *\r
+ * In other words, for each row we create a new instance of\r
+ * this class and call "XMLExists" on that instance.  Then,\r
+ * as seen below, we retrieve the SqlXmlUtil from the activation\r
+ * and pass that into a call to "XMLExists" on the XML value\r
+ * itself (i.e. xcol).  XMLDataValue.XMLExists() then uses the\r
+ * methods and objects (which include the compiled query\r
+ * expression for "/simple") defined on SqlXmlUtil to complete\r
+ * the operation.\r
+ * \r
+ * Okay, so why do we use this execution-time SqlXmlExecutor class\r
+ * instead of just generating a call to XMLDataValue.XMLExists()\r
+ * directly?  The reason is that we only want to compile the XML\r
+ * query expression once per statement--and where possible we'd\r
+ * also like to only generate re-usable XML-specific objects\r
+ * once per statement, as well.  If instead we generated a call to\r
+ * XMLDataValue.XMLExists() directly for each row, then we would\r
+ * have to either pass in the expression string and have XMLDataValue\r
+ * compile it, or we would have to compile the expression string\r
+ * and then pass the compiled object into XMLDataValue--in either\r
+ * case, we'd end up compiling the XML query expression (and creating\r
+ * the corresponding XML-specific objects) once for each row in\r
+ * the target result set.  By using the "saveObject" functionality\r
+ * in Activation along with this SqlXmlExecutor class, we make\r
+ * it so that we only have to compile the XML query expression and\r
+ * create XML-specific objects once (at compile time), and then\r
+ * we can re-use those objects for every row in the target\r
+ * result set.  Yes, we're still creating an instance of this\r
+ * class (SqlXmlExecutor) once per row, and yes we have to fetch\r
+ * the appropriate SqlXmlUtil object once per row, but this is\r
+ * still going to be cheaper than having to re-compile the query\r
+ * expression and re-create XML objects for every row.\r
+ * \r
+ * So in short, this class allows us to improve the execution-time\r
+ * performance of XML operators by allowing us to create XML-\r
+ * specific objects and compile XML query expressions once per\r
+ * statement, instead of once per row.\r
+ *\r
+ * One final note: the reason this class is in this package\r
+ * instead of the types package is that, in order to retrieve\r
+ * the compile-time objects, we have to use the "getSavedObject()"\r
+ * method on the Activation.  But the Activation class is part\r
+ * of the SQL layer (org.apache.derby.iapi.sql.Activation) and\r
+ * we want to keep the types layer independent of the SQL layer\r
+ * because the types can be used during recovery before the SQL\r
+ * system has booted.  So the next logical choices were the compile\r
+ * package (impl.sql.compile) or the execution package; of those,\r
+ * the execution package seems more appropriate since this\r
+ * class is only instantiated and used during execution, not\r
+ * during compilation.\r
+ */\r
+\r
+public class SqlXmlExecutor {\r
+\r
+    // The activation from which we load the compile-time XML\r
+    // objects (including the compiled XML query expression in\r
+    // case of XMLEXISTS and XMLQUERY).\r
+    private Activation activation;\r
+    private int sqlXUtilId;\r
+\r
+    // Target type, target width and target collation type that \r
+    // were specified for an XMLSERIALIZE operator.\r
+    private int targetTypeId;\r
+    private int targetMaxWidth;\r
+    private int targetCollationType;\r
+\r
+    // Whether or not to preserve whitespace for XMLPARSE\r
+    // operator.\r
+    private boolean preserveWS;\r
+\r
+    /**\r
+     * Constructor 1: Used for XMLPARSE op.\r
+     * @param activation Activation from which to retrieve saved objects\r
+     * @param utilId Id by which we find saved objects in activation\r
+     * @param preserveWS Whether or not to preserve whitespace\r
+     */\r
+    public SqlXmlExecutor(Activation activation, int utilId,\r
+        boolean preserveWS)\r
+    {\r
+        this.activation = activation;\r
+        this.sqlXUtilId = utilId;\r
+        this.preserveWS = preserveWS;\r
+    }\r
+\r
+    /**\r
+     * Constructor 2: Used for XMLSERIALIZE op.\r
+     * @param targetTypeId The string type to which we want to serialize.\r
+     * @param targetMaxWidth The max width of the target type.\r
+     * @param targetCollationType The collation type of the target type.\r
+     */\r
+    public SqlXmlExecutor(int targetTypeId, int targetMaxWidth, \r
+               int targetCollationType)\r
+    {\r
+        this.targetTypeId = targetTypeId;\r
+        this.targetMaxWidth = targetMaxWidth;\r
+        this.targetCollationType = targetCollationType;\r
+    }\r
+\r
+    /**\r
+     * Constructor 3: Used for XMLEXISTS/XMLQUERY ops.\r
+     * @param activation Activation from which to retrieve saved objects\r
+     * @param utilId Id by which we find saved objects in activation\r
+     */\r
+    public SqlXmlExecutor(Activation activation, int utilId)\r
+    {\r
+        this.activation = activation;\r
+        this.sqlXUtilId = utilId;\r
+    }\r
+\r
+    /**\r
+     * Make the call to perform an XMLPARSE operation on the\r
+     * received XML string and store the result in the received\r
+     * XMLDataValue (or if it's null, create a new one).\r
+     *\r
+     * @param xmlText String to parse\r
+     * @param result XMLDataValue in which to store the result\r
+     * @return The received XMLDataValue with its content set to\r
+     *  correspond to the received xmlText, if the text constitutes\r
+     *  a valid XML document.  If the received XMLDataValue is\r
+     *  null, then create a new one and set its content to\r
+     *  correspond to the received xmlText.\r
+     */\r
+    public XMLDataValue XMLParse(StringDataValue xmlText, XMLDataValue result)\r
+        throws StandardException\r
+    {\r
+        if (result == null)\r
+            result = new XML();\r
+\r
+        if (xmlText.isNull())\r
+        {\r
+            result.setToNull();\r
+            return result;\r
+        }\r
+\r
+        return result.XMLParse(\r
+            xmlText.getString(), preserveWS, getSqlXmlUtil());\r
+    }\r
+\r
+    /**\r
+     * Make the call to perform an XMLSERIALIZE operation on the\r
+     * received XML data value and store the result in the received\r
+     * StringDataValue (or if it's null, create a new one).\r
+     *\r
+     * @param xmlVal XML value to serialize\r
+     * @param result StringDataValue in which to store the result\r
+     * @return A serialized (to string) version of this XML object,\r
+     *  in the form of a StringDataValue object.  \r
+     */\r
+    public StringDataValue XMLSerialize(XMLDataValue xmlVal,\r
+        StringDataValue result) throws StandardException\r
+    {\r
+        return xmlVal.XMLSerialize(result, targetTypeId, targetMaxWidth, \r
+                       targetCollationType);\r
+    }\r
+\r
+    /**\r
+     * Make the call to perform an XMLEXISTS operation on the\r
+     * received XML data value.\r
+     *\r
+     * @param xExpr Query expression to be evaluated\r
+     * @param xmlContext Context node against which to evaluate\r
+     *  the expression.\r
+     * @return True if evaluation of the query expression\r
+     *  against xmlContext returns at least one item; unknown if\r
+     *  either the xml value is NULL; false otherwise. \r
+     */\r
+    public BooleanDataValue XMLExists(StringDataValue xExpr,\r
+        XMLDataValue xmlContext) throws StandardException\r
+    {\r
+        return xmlContext.XMLExists(getSqlXmlUtil());\r
+    }\r
+\r
+    /**\r
+     * Make the call to perform an XMLQUERY operation on the\r
+     * received XML data value and store the result in the\r
+     * received result holder (or, if it's null, create a\r
+     * new one).\r
+     *\r
+     * @param xExpr Query expression to be evaluated\r
+     * @param xmlContext Context node against which to evaluate\r
+     *  the expression.\r
+     * @param result XMLDataValue in which to store the result\r
+     * @return The received XMLDataValue with its content set to\r
+     *  result of evaulating the query expression against xmlContext.\r
+     *  If the received XMLDataValue is null, then create a new one\r
+     *  and set its content to correspond to the received xmlText.\r
+     */\r
+    public XMLDataValue XMLQuery(StringDataValue xExpr,\r
+        XMLDataValue xmlContext, XMLDataValue result)\r
+        throws StandardException\r
+    {\r
+        return xmlContext.XMLQuery(result, getSqlXmlUtil());\r
+    }\r
+\r
+    /**\r
+     * Return the saved object in this.activation that corresponds to\r
+     * this.sqlxUtilId.  Assumption is that those fields have been\r
+     * set by the time we get here.\r
+     */\r
+    private SqlXmlUtil getSqlXmlUtil()\r
+        throws StandardException\r
+    {\r
+        return (SqlXmlUtil)\r
+            activation.getPreparedStatement().getSavedObject(sqlXUtilId);\r
+    }\r
+\r
+}\r