Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / compile / SQLToJavaValueNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java
new file mode 100644 (file)
index 0000000..c56b4d8
--- /dev/null
@@ -0,0 +1,523 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.SQLToJavaValueNode\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.compile;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.types.JSQLType;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.iapi.sql.compile.TypeCompiler;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.iapi.sql.compile.Visitable;\r
+import org.apache.derby.iapi.sql.compile.Visitor;\r
+\r
+import org.apache.derby.iapi.reference.ClassName;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * This node type converts a value in the SQL domain to a value in the Java\r
+ * domain.\r
+ */\r
+\r
+public class SQLToJavaValueNode extends JavaValueNode\r
+{\r
+       ValueNode       value;\r
+\r
+    /**\r
+     * If set then this SQL value is being passed into a SQL function\r
+     * declared RETURNS NULL ON NULL input. In this case this node\r
+     * performs NULL checking logic in addition simple translation\r
+     * from the SQL domain to the Java domain. Thus if this\r
+     * is set then this node can not be removed when it\r
+     * is paired with a JavaToSQLValueNode.\r
+     * This field is set at generate time of the\r
+     * enclosing StaticMethodCallNode.\r
+     */\r
+       LocalField      returnsNullOnNullState;\r
+\r
+       /**\r
+        * Constructor for a SQLToJavaValueNode\r
+        *\r
+        * @param value         A ValueNode representing a SQL value to convert to\r
+        *                                      the Java domain.\r
+        */\r
+\r
+       public void init(Object value)\r
+       {\r
+               this.value = (ValueNode) value;\r
+       }\r
+\r
+       /**\r
+        * Prints the sub-nodes of this object.  See QueryTreeNode.java for\r
+        * how tree printing is supposed to work.\r
+        *\r
+        * @param depth         The depth of this node in the tree\r
+        */\r
+\r
+       public void printSubNodes(int depth)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       int     parm;\r
+\r
+                       super.printSubNodes(depth);\r
+                       if (value != null)\r
+                       {\r
+                               printLabel(depth, "value: ");\r
+                               value.treePrint(depth + 1);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+         *     Returns the name of the java class type that this node coerces to.\r
+         *\r
+         *     @return name of java class type\r
+         *\r
+         */\r
+       public String getJavaTypeName()\r
+       throws StandardException\r
+       {\r
+               JSQLType        myType = getJSQLType();\r
+\r
+               if ( myType == null ) { return ""; }\r
+               else { return   mapToTypeID( myType ).getCorrespondingJavaTypeName(); }\r
+       }\r
+\r
+       /**\r
+         *     Returns the name of the java primitive type that this node coerces to.\r
+         *\r
+         *     @return name of java primitive type\r
+         *\r
+         * @exception StandardException                Thrown on error\r
+         */\r
+       public String getPrimitiveTypeName()\r
+               throws StandardException\r
+       {\r
+               JSQLType        myType = getJSQLType();\r
+\r
+               if ( myType == null )\r
+               {\r
+                       return "";\r
+               }\r
+               else\r
+               {\r
+                       return\r
+                               getTypeCompiler(mapToTypeID( myType )).\r
+                                                                               getCorrespondingPrimitiveTypeName();\r
+               }\r
+       }\r
+\r
+       /**\r
+         *     Get the JSQLType that corresponds to this node. Could be a SQLTYPE,\r
+         *     a Java primitive, or a Java class.\r
+         *\r
+         *     Overrides method in JavaValueNode.\r
+         *\r
+         *     @return the corresponding JSQLType\r
+         *\r
+         */\r
+       public  JSQLType        getJSQLType     () throws StandardException\r
+       {\r
+               if ( jsqlType == null )\r
+               {\r
+                       if ( value.requiresTypeFromContext()) \r
+                       {\r
+                               ParameterNode pn;\r
+                               if (value instanceof UnaryOperatorNode) \r
+                                       pn = ((UnaryOperatorNode)value).getParameterOperand();\r
+                               else\r
+                                       pn = (ParameterNode) (value);\r
+                               jsqlType = pn.getJSQLType();\r
+                               \r
+                       }\r
+                       else\r
+                       {\r
+                               DataTypeDescriptor dtd = value.getTypeServices();\r
+                               if (dtd != null)\r
+                                       jsqlType = new JSQLType( dtd );\r
+                       }\r
+               }\r
+\r
+               return jsqlType;\r
+       }\r
+\r
+\r
+       /**\r
+        * Bind this expression.  This means binding the sub-expressions,\r
+        * as well as figuring out what the return type is for this expression.\r
+        *\r
+        * @param fromList              The FROM list for the query this\r
+        *                              expression is in, for binding columns.\r
+        * @param subqueryList          The subquery list being built as we find\r
+        *                                                      SubqueryNodes\r
+        * @param aggregateVector       The aggregate vector being built as we find AggregateNodes\r
+        *\r
+        * @return this \r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public JavaValueNode bindExpression(\r
+               FromList fromList, SubqueryList subqueryList,\r
+               Vector  aggregateVector) \r
+                       throws StandardException\r
+       {\r
+               /* Bind the expression under us */\r
+               value = value.bindExpression(fromList, subqueryList,\r
+                                                         aggregateVector);\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Remap all ColumnReferences in this tree to be clones of the\r
+        * underlying expression.\r
+        *\r
+        * @return JavaValueNode                        The remapped expression tree.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public JavaValueNode remapColumnReferencesToExpressions()\r
+               throws StandardException\r
+       {\r
+               value = value.remapColumnReferencesToExpressions();\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Categorize this predicate.  Initially, this means\r
+        * building a bit map of the referenced tables for each predicate.\r
+        * If the source of this ColumnReference (at the next underlying level) \r
+        * is not a ColumnReference or a VirtualColumnNode then this predicate\r
+        * will not be pushed down.\r
+        *\r
+        * For example, in:\r
+        *              select * from (select 1 from s) a (x) where x = 1\r
+        * we will not push down x = 1.\r
+        * NOTE: It would be easy to handle the case of a constant, but if the\r
+        * inner SELECT returns an arbitrary expression, then we would have to copy\r
+        * that tree into the pushed predicate, and that tree could contain\r
+        * subqueries and method calls.\r
+        * RESOLVE - revisit this issue once we have views.\r
+        *\r
+        * @param referencedTabs        JBitSet with bit map of referenced FromTables\r
+        * @param simplePredsOnly       Whether or not to consider method\r
+        *                                                      calls, field references and conditional nodes\r
+        *                                                      when building bit map\r
+        *\r
+        * @return boolean              Whether or not source.expression is a ColumnReference\r
+        *                                              or a VirtualColumnNode.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)\r
+               throws StandardException\r
+       {\r
+               return value.categorize(referencedTabs, simplePredsOnly);\r
+       }\r
+\r
+       /**\r
+        * Preprocess an expression tree.  We do a number of transformations\r
+        * here (including subqueries, IN lists, LIKE and BETWEEN) plus\r
+        * subquery flattening.\r
+        * NOTE: This is done before the outer ResultSetNode is preprocessed.\r
+        *\r
+        * @param       numTables                       Number of tables in the DML Statement\r
+        * @param       outerFromList           FromList from outer query block\r
+        * @param       outerSubqueryList       SubqueryList from outer query block\r
+        * @param       outerPredicateList      PredicateList from outer query block\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void preprocess(int numTables,\r
+                                                       FromList outerFromList,\r
+                                                       SubqueryList outerSubqueryList,\r
+                                                       PredicateList outerPredicateList) \r
+                                                       throws StandardException\r
+       {\r
+               value.preprocess(numTables,\r
+                                                outerFromList, outerSubqueryList,\r
+                                                outerPredicateList);\r
+       }\r
+\r
+       /**\r
+        * Return the variant type for the underlying expression.\r
+        * The variant type can be:\r
+        *              VARIANT                         - variant within a scan\r
+        *                                                        (method calls and non-static field access)\r
+        *              SCAN_INVARIANT          - invariant within a scan\r
+        *                                                        (column references from outer tables)\r
+        *              QUERY_INVARIANT         - invariant within the life of a query\r
+        *                                                        (constant expressions)\r
+        *\r
+        * @return      The variant type for the underlying expression.\r
+        * @exception StandardException thrown on error\r
+        */\r
+       protected int getOrderableVariantType() throws StandardException\r
+       {\r
+               return value.getOrderableVariantType();\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      CODE GENERATION METHODS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+\r
+       /**\r
+        * Generate code to get the Java value out of a SQL value.\r
+        *\r
+        * Every SQL type has a corresponding Java type.  The getObject() method\r
+        * on the SQL type gets the right Java type.\r
+        *\r
+        * The generated code will be:\r
+        *\r
+        * (<Java type name>) ((DataValueDescriptor)\r
+        *                                                              <generated value>.getObject())\r
+        *\r
+        * where <Java type name> comes from the getCorrespondingJavaTypeName()\r
+        * method of the value's TypeId.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {       \r
+               /* Compile the expression under us */\r
+               generateSQLValue( acb, mb );\r
+\r
+               /* now cast the SQLValue to a Java value */\r
+               generateJavaValue( acb, mb);\r
+       }\r
+\r
+       /**\r
+        * Generate the SQLvalue that this node wraps.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       private void generateSQLValue(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {\r
+               value.generateExpression(acb, mb);\r
+       }\r
+\r
+       /**\r
+        * Generate code to cast the SQLValue to a Java value.\r
+        *\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mbex  The method the expression will go into\r
+        *\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       private void generateJavaValue\r
+       (\r
+               ExpressionClassBuilder  acb,\r
+               MethodBuilder mbex\r
+    )\r
+               throws StandardException\r
+       {\r
+               /* If this is a conversion to a primitive type, then call the\r
+                * appropriate method for getting the primitive value and\r
+                * cast it to the primitive type. \r
+                * NOTE: We first call Activation.nullToPrimitiveTest(),\r
+                * which will throw a StandardException if the value is null\r
+                */\r
+               if ( isPrimitiveType() || mustCastToPrimitive() )\r
+               {\r
+                       String          primitiveTN = value.getTypeCompiler().getCorrespondingPrimitiveTypeName();\r
+\r
+                       /* Put the code to check if the object is null and to\r
+                        * get the primitive value in a method call.  This is\r
+                        * necessary because we are generating an expression here and\r
+                        * cannot have multiple statements.\r
+                        * The method call will take SQLValue as a parameter.\r
+                        */\r
+                       String[] pd = new String[1];\r
+                       pd[0] = getSQLValueInterfaceName(); // parameter "param1"\r
+\r
+                       MethodBuilder   mb = acb.newGeneratedFun(primitiveTN, Modifier.PRIVATE, pd);\r
+\r
+                       mb.getParameter(0);\r
+\r
+                       if (returnsNullOnNullState != null)\r
+                       {\r
+                               generateReturnsNullOnNullCheck(mb);\r
+                       }\r
+                       else\r
+                       {\r
+                               mb.dup();\r
+                               mb.upCast(ClassName.DataValueDescriptor);\r
+                               mb.push(primitiveTN); \r
+                               mb.callMethod(VMOpcode.INVOKESTATIC, ClassName.BaseActivation, "nullToPrimitiveTest", "void", 2);\r
+                       }\r
+\r
+                       // stack is dvd\r
+\r
+                       /* Generate the code to get the primitive value */\r
+                       mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor,\r
+                                                               value.getTypeCompiler().getPrimitiveMethodName(), primitiveTN, 0);\r
+\r
+                       mb.methodReturn();\r
+                       mb.complete();\r
+\r
+                       /* Generate the call to the new method, with the parameter */\r
+\r
+                       mbex.pushThis();\r
+                       mbex.swap(); // caller pushed out parameter\r
+                       mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), primitiveTN, 1);\r
+               }\r
+               else\r
+               {\r
+                       if (returnsNullOnNullState != null)\r
+                               generateReturnsNullOnNullCheck(mbex);\r
+\r
+                       /* Call getObject() to get the right type of Java value */\r
+                       mbex.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "getObject",\r
+                                                                               "java.lang.Object", 0);\r
+\r
+                       mbex.cast(value.getTypeId().getCorrespondingJavaTypeName());\r
+               }\r
+       }\r
+\r
+       /**\r
+               Generate the code for the returns Null on Null input check..\r
+               Stack must contain the DataDescriptorValue.\r
+       */\r
+\r
+       private void generateReturnsNullOnNullCheck(MethodBuilder mb)\r
+       {\r
+               mb.dup();\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Storable,\r
+                                                               "isNull", "boolean", 0);\r
+\r
+               mb.conditionalIf();\r
+                 mb.push(true);\r
+               mb.startElseCode();\r
+                 mb.getField(returnsNullOnNullState);\r
+               mb.completeConditional();\r
+               \r
+               mb.setField(returnsNullOnNullState);\r
+       }\r
+\r
+\r
+       /**\r
+         *     Get the type name of the SQLValue we generate.\r
+         *\r
+         *     @return name of interface corresponding to SQLValue\r
+         *\r
+         *\r
+         * @exception StandardException                Thrown on error\r
+         */\r
+       private String  getSQLValueInterfaceName()\r
+               throws StandardException\r
+       {\r
+               return value.getTypeCompiler().interfaceName();\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      OTHER VALUE NODE METHODS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+\r
+       /**\r
+        * Get the SQL ValueNode that is being converted to a JavaValueNode\r
+        *\r
+        * @return      The underlying SQL ValueNode\r
+        */\r
+       ValueNode getSQLValueNode()\r
+       {\r
+               return value;\r
+       }\r
+\r
+       /** @see ValueNode#getConstantValueAsObject \r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       Object getConstantValueAsObject()\r
+               throws StandardException\r
+       {\r
+               return value.getConstantValueAsObject();\r
+       }\r
+\r
+       /**\r
+        * Accept a visitor, and call v.visit()\r
+        * on child nodes as necessary.  \r
+        * \r
+        * @param v the visitor\r
+        *\r
+        * @exception StandardException on error\r
+        */\r
+       public Visitable accept(Visitor v) \r
+               throws StandardException\r
+       {\r
+               Visitable returnNode = v.visit(this);\r
+       \r
+               if (v.skipChildren(this))\r
+               {\r
+                       return returnNode;\r
+               }\r
+\r
+               if (value != null && !v.stopTraversal())\r
+               {\r
+                       value = (ValueNode)value.accept(v);\r
+               }\r
+\r
+               return returnNode;\r
+       }\r
+}\r