Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / ParameterNode.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java
new file mode 100644 (file)
index 0000000..b89dcc1
--- /dev/null
@@ -0,0 +1,524 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.ParameterNode\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 java.sql.Types;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.JSQLType;\r
+import org.apache.derby.iapi.types.TypeId;\r
+\r
+/**\r
+ * This node type represents a ? parameter.\r
+ *\r
+ */\r
+\r
+public class ParameterNode extends ValueNode\r
+{\r
+\r
+       /*\r
+       ** The parameter number for this parameter.  The numbers start at 0.\r
+       */\r
+       private int     parameterNumber;\r
+\r
+       /**\r
+       ** Pointer to the array in the CompilerContext that holds array\r
+    * of types for all the user-visible paramerers..  When each parameter is\r
+       ** bound, it fills in its type descriptor in this array.  Note that\r
+       ** the array is allocated in the parser, but the individual elements\r
+       ** are not filled in until their corresponding parameters are bound.\r
+    *\r
+    * This array is not read in this class, but is read from the\r
+    * CompilerContext on completion of compiling the statement.\r
+    * \r
+    *  In some case a parameter node may exist but is not a visble\r
+    *  user parameter, in this case typeServices will be null\r
+    *  so that setting its type will not modify the user's set.\r
+       */\r
+\r
+       private DataTypeDescriptor[]    userParameterTypes;\r
+\r
+       /*\r
+       ** The default value for this parameter.  Currently, the only\r
+       ** reason for a parameter having a default value is for a\r
+       ** stored prepared statement, where they are supplied for\r
+       ** optimization.\r
+       */\r
+       private DataValueDescriptor             defaultValue;\r
+\r
+       /**\r
+         *     This ParameterNode may turn up as an argument to a replicated Work Unit.\r
+         *     If so, the remote system will have figured out the type of this node.\r
+         *     That's what this variable is for.\r
+         */\r
+       private JSQLType                        jsqlType;\r
+\r
+       private int orderableVariantType = Qualifier.QUERY_INVARIANT;\r
+\r
+       /**\r
+        * By default, we assume we are just a normal, harmless\r
+        * little ole parameter.  But sometimes we may be a return\r
+        * parameter (e.g. ? = CALL myMethod()).  \r
+        */\r
+       private ValueNode returnOutputParameter;\r
+\r
+       /**\r
+        * If this parameter node was created as part of a "probe predicate"\r
+        * for an InListOperatorNode then it does not actually correspond to\r
+        * a specific value--we just created it as a start-key place-holder\r
+        * for IN-list values at execution time.  In order to serve that\r
+        * purpose we need to generate some value that can be used as the\r
+        * place-holder.  Since this parameter node is "fake" and does not\r
+        * correspond to an actual parameter, we can't really generate it;\r
+        * so the following field holds some legitimate ValueNode--either a\r
+        * constant node or a "real" parameter node--that we can generate to\r
+        * serve as the place-holder.\r
+        */\r
+       private ValueNode valToGenerate;\r
+\r
+       /**\r
+        * Constructor for use by the NodeFactory\r
+        */\r
+       public ParameterNode()\r
+       {\r
+       }\r
+\r
+       /**\r
+        * Initializer for a ParameterNode.\r
+        *\r
+        * @param parameterNumber                       The number of this parameter,\r
+        *                                                                      (unique per query starting at 0)\r
+        * @param defaultValue                          The default value for this parameter\r
+        *\r
+        */\r
+\r
+       public void init(Object parameterNumber, Object defaultValue)\r
+       {\r
+               this.defaultValue = (DataValueDescriptor) defaultValue;\r
+               this.parameterNumber = ((Integer) parameterNumber).intValue();\r
+       }\r
+\r
+       /**\r
+        * Get the parameter number\r
+        *\r
+        * @return      The parameter number\r
+        */\r
+\r
+       int getParameterNumber()\r
+       {\r
+               return parameterNumber;\r
+       }\r
+\r
+       /**\r
+        * Set the descriptor array\r
+        *\r
+        * @param       descriptors     The array of DataTypeServices to fill in when the parameters\r
+        *                      are bound.\r
+        */\r
+\r
+       void setDescriptors(DataTypeDescriptor[] descriptors)\r
+       {\r
+               userParameterTypes = descriptors;\r
+       }\r
+\r
+       /**\r
+        * Set the DataTypeServices for this parameter\r
+        *\r
+        * @param descriptor    The DataTypeServices to set for this parameter\r
+        */\r
+\r
+       public void setType(DataTypeDescriptor descriptor) throws StandardException\r
+       {\r
+               /* Make sure the type is nullable. */\r
+\r
+               /*\r
+                ** Generate a new descriptor with all the same properties as\r
+                ** the given one, except that it is nullable.\r
+                */\r
+               descriptor = descriptor.getNullabilityType(true);\r
+               \r
+\r
+        if (userParameterTypes != null)\r
+                   userParameterTypes[parameterNumber] = descriptor;\r
+\r
+               //make sure we are calling super's setType. We will get into\r
+               //an infinite loop if this setType ends up calling the local\r
+               //setType method\r
+               super.setType(descriptor);\r
+\r
+               if ( getJSQLType() == null ) { setJSQLType(  new JSQLType( descriptor ) ); }\r
+       }\r
+\r
+       /**\r
+        * Mark this as a return output parameter (e.g.\r
+        * ? = CALL myMethod())\r
+        */\r
+       public void setReturnOutputParam(ValueNode valueNode)\r
+       {\r
+               returnOutputParameter = valueNode;\r
+       }\r
+\r
+       /**\r
+        * Is this as a return output parameter (e.g.\r
+        * ? = CALL myMethod())\r
+        *\r
+        * @return true if it is a return param\r
+        */\r
+       public boolean isReturnOutputParam()\r
+       {\r
+               return returnOutputParameter != null;\r
+       }\r
+\r
+       /**\r
+        * Bind this expression.  A parameter can't figure out what its type\r
+        * is without knowing where it appears, so this method does nothing.\r
+        * It is up to the node that points to this parameter node to figure\r
+        * out the type of the parameter and set it, using the setType()\r
+        * method above.\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 SubqueryNodes\r
+        * @param aggregateVector       The aggregate vector being built as we find AggregateNodes\r
+        *\r
+        * @return      The new top of the expression tree.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+\r
+       public ValueNode bindExpression(\r
+                       FromList fromList, SubqueryList subqueryList,\r
+                       Vector  aggregateVector) \r
+                               throws StandardException\r
+       {\r
+               checkReliability( "?", CompilerContext.UNNAMED_PARAMETER_ILLEGAL );\r
+\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not this expression tree represents a constant expression.\r
+        *\r
+        * @return      Whether or not this expression tree represents a constant expression.\r
+        */\r
+       public boolean isConstantExpression()\r
+       {\r
+               return true;\r
+       }\r
+\r
+       /** @see ValueNode#constantExpression */\r
+       public boolean constantExpression(PredicateList whereClause)\r
+       {\r
+               return true;\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
+        */\r
+       protected int getOrderableVariantType()\r
+       {\r
+               // Parameters are invariant for the life of the query\r
+               return orderableVariantType;\r
+       }\r
+\r
+       /**\r
+        * In a special circumstance, we want to consider\r
+        * parameters as constants.  For that situation, we\r
+        * allow a caller to temporarily set us to CONSTANT\r
+        * and then restore us.\r
+        */\r
+       void setOrderableVariantType(int type)\r
+       {\r
+               orderableVariantType = type;\r
+       }\r
+\r
+       ////////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      OVERRIDE METHODS IN VALUE NODE THAT ARE USED WHILE BINDING REPLICATED\r
+       //      CALL WORK STATEMENTS.\r
+       //\r
+       //      In this scenario, a JSQLType was replicated along with this parameter.\r
+       //      The JSQLType represents the bind() decision of the remote system, which\r
+       //      we want to reproduce locally.\r
+       //\r
+       ////////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+         *     Set the JSQLType of this parameter. This supports the unnamed parameters\r
+         *     that we use for replicated work units.\r
+         *\r
+         *     @param  type    the JSQLType associated with this parameter\r
+         */\r
+       public  void    setJSQLType\r
+       (\r
+               JSQLType        type\r
+       )\r
+       { jsqlType = type; }\r
+\r
+       /**\r
+         *     Get the JSQLType associated with this parameter. Again, part of method\r
+         *     resolution for replicated work units.\r
+         *\r
+         *     @return the JSQLType that the remote system assigned\r
+         */\r
+       public  JSQLType        getJSQLType()\r
+       {\r
+               return jsqlType;\r
+       }\r
+\r
+\r
+       ////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      CODE GENERATOR\r
+       //\r
+       ////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * For a ParameterNode, we generate for the return value:\r
+        *\r
+        *              (<java type name>)\r
+        *                      ( (BaseActivation) this.getParameter(parameterNumber) )\r
+        *\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
+       public void generateExpression(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {\r
+               /* If we were given a specific ValueNode to generate then\r
+                * just use that.  See, in particular, the preprocess method\r
+                * of InListOperatorNode.\r
+                */\r
+               if (valToGenerate != null)\r
+               {\r
+                       valToGenerate.generateExpression(acb, mb);\r
+                       return;\r
+               }\r
+\r
+               DataTypeDescriptor dtd = getTypeServices();\r
+               if ((dtd != null) && dtd.getTypeId().isXMLTypeId()) {\r
+               // We're a parameter that corresponds to an XML column/target,\r
+               // which we don't allow.  We throw the error here instead of\r
+               // in "bindExpression" because at the time of bindExpression,\r
+               // we don't know yet what the type is going to be (only when\r
+               // the node that points to this parameter calls\r
+               // "setType" do we figure out the type).\r
+                       throw StandardException.newException(\r
+                               SQLState.LANG_ATTEMPT_TO_BIND_XML);\r
+               }\r
+\r
+        /* Generate the return value */\r
+\r
+        mb.pushThis();\r
+        mb.push(parameterNumber); // arg\r
+\r
+        mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getParameter",\r
+                      ClassName.DataValueDescriptor, 1);\r
+\r
+               // For some types perform host variable checking\r
+               // to match DB2/JCC where if a host variable is too\r
+               // big it is not accepted, regardless of any trailing padding.\r
+\r
+               switch (dtd.getJDBCTypeId()) {\r
+               case Types.BINARY:\r
+               case Types.VARBINARY:\r
+               case Types.LONGVARBINARY:\r
+               case Types.BLOB:\r
+                       mb.dup();\r
+                       mb.push(dtd.getMaximumWidth());\r
+                       mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "checkHostVariable",\r
+                      "void", 1);\r
+                       break;\r
+\r
+               default:\r
+                       break;\r
+               }\r
+\r
+        /* Cast the result to its specific interface */\r
+        mb.cast(getTypeCompiler().interfaceName());\r
+       } // End of generateExpression\r
+\r
+       public TypeId getTypeId() throws StandardException\r
+       {\r
+               return (returnOutputParameter != null) ?\r
+                       returnOutputParameter.getTypeId() : super.getTypeId();\r
+       }\r
+\r
+       ////////////////////////////////////////////////////////////////////\r
+       //\r
+       //      STATIC ROUTINES\r
+       //\r
+       ////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * Generate the code to create the ParameterValueSet, if necessary,\r
+        * when constructing the activation.  Also generate the code to call\r
+        * a method that will throw an exception if we try to execute without\r
+        * all the parameters being set.\r
+        * \r
+        * This generated code goes into the Activation's constructor early on.\r
+        * \r
+        * @param acb                                   The ExpressionClassBuilder for the class we're building\r
+        * @param numberOfParameters    number of parameters for this statement\r
+        * @param parameterList                 The parameter list for the statement.\r
+        *\r
+        * @exception StandardException on error\r
+        */\r
+       static public   void generateParameterValueSet(ExpressionClassBuilder   acb,\r
+                                                                  int          numberOfParameters,\r
+                                                                  Vector       parameterList)\r
+               throws StandardException\r
+       {\r
+               if (numberOfParameters > 0)\r
+               {\r
+                       MethodBuilder   constructor = acb.getConstructor();\r
+\r
+                       /*\r
+                       ** Check the first parameter to see if it is a return\r
+                       ** parameter.\r
+                       */\r
+                       boolean hasReturnParam = ((ParameterNode)parameterList.elementAt(0)).isReturnOutputParam();\r
+\r
+                       /*\r
+                       ** Generate the following:\r
+                       **\r
+                       ** pvs =\r
+                       **              getLanguageConnectionContext()\r
+                       **                      .getLanguageFactory()\r
+                       **                                      .getParameterValueSet(numberOfParameters);\r
+                       **\r
+                       ** pvs is a ParameterValueSet that lives in the superclass of\r
+                       ** the activation being generated.\r
+                       */\r
+\r
+                       constructor.pushThis(); // for the put field down below\r
+\r
+                       /* Generate the call to getContext */\r
+                       //?X constructor.pushThis();\r
+                       //?Xconstructor.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation, "getLanguageConnectionContext",\r
+                       //?X                                    ClassName.LanguageConnectionContext, 0);\r
+                       /*\r
+                       ** Call getLanguageFactory()\r
+                       */\r
+                       //?Xconstructor.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getLanguageFactory",\r
+                       //?X                                    ClassName.LanguageFactory, 0);\r
+\r
+                       /*\r
+                       ** Call getParameterValueSet(<number of parameters>, <hasReturnParam>)\r
+                       */\r
+\r
+                       constructor.push(numberOfParameters); // first arg\r
+                       constructor.push(hasReturnParam); // second arg\r
+\r
+                       constructor.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation,\r
+                                                                       "setParameterValueSet", "void", 2);\r
+\r
+                       //?Xconstructor.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getParameterValueSet",\r
+                       //?X                                    ClassName.ParameterValueSet, 2);\r
+\r
+                       /* Assign the return from getParameterValueSet() to the field */\r
+                       //?Xconstructor.putField(ClassName.BaseActivation, "pvs", ClassName.ParameterValueSet);\r
+                       //?Xconstructor.endStatement();\r
+\r
+                       /*\r
+                       ** Add a call to the execute() method to check\r
+                       ** for missing parameters\r
+                       */\r
+                       MethodBuilder   executeMethod = acb.getExecuteMethod();\r
+\r
+                       executeMethod.pushThis();\r
+                       executeMethod.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "throwIfMissingParms", "void", 0);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Get the default value for the parameter.  Parameters\r
+        * may get default values for optimization purposes.\r
+        *\r
+        * @return the value, may be null\r
+        */\r
+       DataValueDescriptor getDefaultValue()\r
+       {\r
+               return defaultValue;\r
+       }\r
+\r
+       /**\r
+        * @see ValueNode#requiresTypeFromContext\r
+        */\r
+       public boolean requiresTypeFromContext()\r
+       {\r
+               return true;\r
+       }\r
+       \r
+       /**\r
+        * @see ValueNode#isParameterNode\r
+        */\r
+       public boolean isParameterNode()\r
+       {\r
+               return true;\r
+       }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected boolean isEquivalent(ValueNode o)\r
+    {\r
+       return false;\r
+    }\r
+\r
+    /**\r
+     * Save the received ValueNode locally so that we can generate it\r
+     * (in place of "this") at generation time.  See the preprocess()\r
+     * method of InListOperatorNode for more on how this is used.\r
+     *\r
+     * @param vn The ValueNode to generate in place of this ParameterNode.\r
+     */\r
+    protected void setValueToGenerate(ValueNode vn)\r
+    {\r
+        valToGenerate = vn;\r
+    }\r
+}\r