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 / NewInvocationNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/NewInvocationNode.java
new file mode 100644 (file)
index 0000000..3f8d903
--- /dev/null
@@ -0,0 +1,539 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.NewInvocationNode\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.loader.ClassInspector;\r
+\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.i18n.MessageService;\r
+\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+\r
+import org.apache.derby.catalog.AliasInfo;\r
+import org.apache.derby.catalog.TypeDescriptor;\r
+\r
+import java.lang.reflect.Member;\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.util.Vector;\r
+import java.util.Enumeration;\r
+\r
+/**\r
+ * A NewInvocationNode represents a new object() invocation.\r
+ *\r
+ */\r
+public class NewInvocationNode extends MethodCallNode\r
+{\r
+       // Whether or not to do a single instantiation\r
+       private boolean singleInstantiation = false;\r
+\r
+       private boolean delimitedIdentifier;\r
+\r
+       /**\r
+        * Initializer for a NewInvocationNode. Parameters are:\r
+        *\r
+        * <ul>\r
+        * <li>javaClassName            The full package.class name of the class</li>\r
+        * <li>parameterList            The parameter list for the constructor</li>\r
+        * </ul>\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void init(\r
+                                       Object javaClassName,\r
+                                       Object params,\r
+                                       Object delimitedIdentifier)\r
+               throws StandardException\r
+       {\r
+               super.init("<init>");\r
+               addParms((Vector) params);\r
+\r
+               this.javaClassName = (String) javaClassName;\r
+               this.delimitedIdentifier =\r
+                                ((Boolean) delimitedIdentifier).booleanValue();\r
+       }\r
+\r
+       /* This version of the "init" method is used for mapping a table name\r
+        * or table function name to a corresponding VTI class name.  The VTI\r
+        * is then invoked as a regular NEW invocation node.\r
+        *\r
+        * There are two kinds of VTI mappings that we do: the first is for\r
+        * "table names", the second is for "table function names".  Table\r
+        * names can only be mapped to VTIs that do not accept any arguments;\r
+        * any VTI that has at least one constructor which accepts one or more\r
+        * arguments must be mapped from a table *function* name.  The way we\r
+        * tell the difference is by looking at the received arguments: if\r
+        * the vtiTableFuncName that we receive is null then we are mapping\r
+        * a "table name" and tableDescriptor must be non-null; if the\r
+        * vtiTableFuncName is non-null then we are mapping a "table\r
+        * function name" and tableDescriptor must be null.\r
+        *\r
+        * Note that we could have just used a single "init()" method and\r
+        * performed the mappings based on what type of Object "javaClassName"\r
+        * was (String, TableDescriptor, or TableName), but making this VTI\r
+        * mapping method separate from the "normal" init() method seems\r
+        * cleaner...\r
+        *\r
+        * @param vtiTableFuncName A TableName object holding a qualified name\r
+        *  that maps to a VTI which accepts arguments.  If vtiTableFuncName is\r
+        *  null then tableDescriptor must NOT be null.\r
+        * @param tableDescriptor A table descriptor that corresponds to a\r
+        *  table name (as opposed to a table function name) that will be\r
+        *  mapped to a no-argument VTI.  If tableDescriptor is null then\r
+        *  vtiTableFuncName should not be null.\r
+        * @param params Parameter list for the VTI constructor.\r
+        * @param delimitedIdentifier Whether or not the target class name\r
+        *  is a delimited identifier.\r
+        */\r
+       public void init(\r
+                                       Object vtiTableFuncName,\r
+                                       Object tableDescriptor,\r
+                                       Object params,\r
+                                       Object delimitedIdentifier)\r
+               throws StandardException\r
+       {\r
+               super.init("<init>");\r
+               addParms((Vector) params);\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       // Exactly one of vtiTableFuncName or tableDescriptor should\r
+                       // be null.\r
+                       SanityManager.ASSERT(\r
+                               ((vtiTableFuncName == null) && (tableDescriptor != null)) ||\r
+                               ((vtiTableFuncName != null) && (tableDescriptor == null)),\r
+                               "Exactly one of vtiTableFuncName or tableDescriptor should " +\r
+                               "be null, but neither or both of them were null.");\r
+               }\r
+\r
+               TableName vtiName = (TableName)vtiTableFuncName;\r
+               TableDescriptor td = (TableDescriptor)tableDescriptor;\r
+               boolean isTableFunctionVTI = (vtiTableFuncName != null);\r
+               if (isTableFunctionVTI)\r
+               {\r
+                       // We have to create a generic TableDescriptor to\r
+                       // pass to the data dictionary.\r
+                       td = new TableDescriptor(getDataDictionary(),\r
+                                       vtiName.getTableName(),\r
+                                       getSchemaDescriptor(vtiName.getSchemaName()),\r
+                                       TableDescriptor.VTI_TYPE,\r
+                                       TableDescriptor.DEFAULT_LOCK_GRANULARITY);\r
+               }\r
+\r
+               /* Use the table descriptor to figure out what the corresponding\r
+                * VTI class name is; we let the data dictionary do the mapping\r
+                * for us.\r
+                */\r
+               this.javaClassName = getDataDictionary().getVTIClass(\r
+                       td, isTableFunctionVTI);\r
+\r
+               /* If javaClassName is still null at this point then we\r
+                * could not find the target class for the received table\r
+                * (or table function) name.  So throw the appropriate\r
+                * error.\r
+                */\r
+               if (this.javaClassName == null)\r
+               {\r
+                       if (!isTableFunctionVTI)\r
+                       {\r
+                               /* Create a TableName object from the table descriptor\r
+                                * that we received.  This gives us the name to use\r
+                                * in the error message.\r
+                                */\r
+                               vtiName = makeTableName(td.getSchemaName(),\r
+                                       td.getDescriptorName());\r
+                       }\r
+\r
+                       throw StandardException.newException(\r
+                               isTableFunctionVTI\r
+                                       ? SQLState.LANG_NO_SUCH_METHOD_ALIAS\r
+                                       : SQLState.LANG_TABLE_NOT_FOUND,\r
+                               vtiName.getFullTableName());\r
+               }\r
+\r
+               this.delimitedIdentifier =\r
+                                ((Boolean) delimitedIdentifier).booleanValue();\r
+       }\r
+\r
+       /**\r
+        * Mark this node as only needing to\r
+        * to a single instantiation.  (We can\r
+        * reuse the object after newing it.)\r
+        */\r
+       void setSingleInstantiation()\r
+       {\r
+               singleInstantiation = true;\r
+       }\r
+\r
+       /**\r
+         *     Get the resolved Classes of our parameters\r
+         *\r
+         *     @return the Classes of our parameters\r
+         */\r
+       public  Class[] getMethodParameterClasses() \r
+       { \r
+               ClassInspector ci = getClassFactory().getClassInspector();\r
+\r
+               Class[] parmTypeClasses = new Class[methodParms.length];\r
+               for (int i = 0; i < methodParms.length; i++)\r
+               {\r
+                       String className = methodParameterTypes[i];\r
+                       try\r
+                       {\r
+                               parmTypeClasses[i] = ci.getClass(className);\r
+                       }\r
+                       catch (ClassNotFoundException cnfe)\r
+                       {\r
+                               /* We should never get this exception since we verified \r
+                                * that the classes existed at bind time.  Just return null.\r
+                                */\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       SanityManager.THROWASSERT("Unexpected exception", cnfe);\r
+                               }\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               return parmTypeClasses;\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 SubqueryNodes\r
+        * @param aggregateVector       The aggregate vector being built as we find AggregateNodes\r
+        *\r
+        * @return      Nothing\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
+               bindParameters(fromList, subqueryList, aggregateVector);\r
+\r
+               verifyClassExist(javaClassName);\r
+               /*\r
+               ** Get the parameter type names out of the parameters and put them\r
+               ** in an array.\r
+               */\r
+               String[]        parmTypeNames = getObjectSignature();\r
+               boolean[]       isParam = getIsParam();\r
+               ClassInspector classInspector = getClassFactory().getClassInspector();\r
+\r
+               /*\r
+               ** Find the matching constructor.\r
+               */\r
+               try\r
+               {\r
+                       /* First try with built-in types and mappings */\r
+                       method = classInspector.findPublicConstructor(javaClassName,\r
+                                                                                       parmTypeNames, null, isParam);\r
+\r
+                       /* If no match, then retry to match any possible combinations of\r
+                        * object and primitive types.\r
+                        */\r
+                       if (method == null)\r
+                       {\r
+                               String[] primParmTypeNames = getPrimitiveSignature(false);\r
+                               method = classInspector.findPublicConstructor(javaClassName,\r
+                                                               parmTypeNames, primParmTypeNames, isParam);\r
+                       }\r
+               }\r
+               catch (ClassNotFoundException e)\r
+               {\r
+                       /*\r
+                       ** If one of the classes couldn't be found, just act like the\r
+                       ** method couldn't be found.  The error lists all the class names,\r
+                       ** which should give the user enough info to diagnose the problem.\r
+                       */\r
+                       method = null;\r
+               }\r
+\r
+               if (method == null)\r
+               {\r
+                       /* Put the parameter type names into a single string */\r
+                       String  parmTypes = "";\r
+                       for (int i = 0; i < parmTypeNames.length; i++)\r
+                       {\r
+                               if (i != 0)\r
+                                       parmTypes += ", ";\r
+                               parmTypes += (parmTypeNames[i].length() != 0 ?\r
+                                                               parmTypeNames[i] :\r
+                                                               MessageService.getTextMessage(\r
+                                                                       SQLState.LANG_UNTYPED)\r
+                                                                       );\r
+                       }\r
+\r
+                       throw StandardException.newException(SQLState.LANG_NO_CONSTRUCTOR_FOUND, \r
+                                                                                                       javaClassName,\r
+                                                                                                       parmTypes);\r
+               }\r
+\r
+               methodParameterTypes = classInspector.getParameterTypes(method);\r
+\r
+               for (int i = 0; i < methodParameterTypes.length; i++)\r
+               {\r
+                       if (classInspector.primitiveType(methodParameterTypes[i]))\r
+                               methodParms[i].castToPrimitive(true);\r
+               }\r
+\r
+               /* Set type info for any null parameters */\r
+               if ( someParametersAreNull() )\r
+               {\r
+                       setNullParameterInfo(methodParameterTypes);\r
+               }\r
+\r
+               /* Constructor always returns an object of type javaClassName */\r
+               if (SanityManager.DEBUG) {\r
+                       SanityManager.ASSERT(javaClassName.equals(classInspector.getType(method)),\r
+                               "Constructor is wrong type, expected " + javaClassName + \r
+                               " actual is " + classInspector.getType(method));\r
+               }\r
+               setJavaTypeName( javaClassName );\r
+               if (routineInfo != null)\r
+                {\r
+                    TypeDescriptor returnType = routineInfo.getReturnType();\r
+                    if (returnType != null)\r
+                    {\r
+                        setCollationType(returnType.getCollationType());\r
+                    }\r
+                }\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
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)\r
+               throws StandardException\r
+       {\r
+               /* We stop here when only considering simple predicates\r
+                *  as we don't consider new opeators when looking\r
+                * for null invariant predicates.\r
+                */\r
+               if (simplePredsOnly)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               boolean pushable = true;\r
+\r
+               pushable = pushable && super.categorize(referencedTabs, simplePredsOnly);\r
+\r
+               return pushable;\r
+       }\r
+\r
+       /**\r
+        * Build a JBitSet of all of the tables that we are\r
+        * correlated with.\r
+        *\r
+        * @param correlationMap        The JBitSet of the tables that we are correlated with.\r
+        */\r
+       void getCorrelationTables(JBitSet correlationMap)\r
+               throws StandardException\r
+       {\r
+               CollectNodesVisitor getCRs = new CollectNodesVisitor(ColumnReference.class);\r
+               super.accept(getCRs);\r
+               Vector colRefs = getCRs.getList();\r
+               for (Enumeration e = colRefs.elements(); e.hasMoreElements(); )\r
+               {\r
+                       ColumnReference ref = (ColumnReference)e.nextElement();\r
+                       if (ref.getCorrelated())\r
+                       {\r
+                               correlationMap.set(ref.getTableNumber());\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Is this class assignable to the specified class?\r
+        * This is useful for the VTI interface where we want to see\r
+        * if the class implements java.sql.ResultSet.\r
+        *\r
+        * @param toClassName   The java class name we want to assign to\r
+        *\r
+        * @return boolean              Whether or not this class is assignable to\r
+        *                                              the specified class\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       protected boolean assignableTo(String toClassName) throws StandardException\r
+       {\r
+               ClassInspector classInspector = getClassFactory().getClassInspector();\r
+               return classInspector.assignableTo(javaClassName, toClassName);\r
+       }\r
+\r
+\r
+       /**\r
+        * Is this class have a public method with the specified signiture\r
+        * This is useful for the VTI interface where we want to see\r
+        * if the class has the option static method for returning the\r
+        * ResultSetMetaData.\r
+        *\r
+        * @param methodName    The method name we are looking for\r
+        * @param staticMethod  Whether or not the method we are looking for is static\r
+        *\r
+        * @return Member               The Member representing the method (or null\r
+        *                                              if the method doesn't exist).\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       protected Member findPublicMethod(String methodName, boolean staticMethod)\r
+               throws StandardException\r
+       {\r
+               Member publicMethod;\r
+\r
+               /*\r
+               ** Get the parameter type names out of the parameters and put them\r
+               ** in an array.\r
+               */\r
+               String[]        parmTypeNames = getObjectSignature();\r
+               boolean[]       isParam = getIsParam();\r
+\r
+               ClassInspector classInspector = getClassFactory().getClassInspector();\r
+\r
+               try\r
+               {\r
+                       publicMethod = classInspector.findPublicMethod(javaClassName, methodName,\r
+                                                                                          parmTypeNames, null, isParam, staticMethod, false);\r
+\r
+                       /* If no match, then retry to match any possible combinations of\r
+                        * object and primitive types.\r
+                        */\r
+                       if (publicMethod == null)\r
+                       {\r
+                               String[] primParmTypeNames = getPrimitiveSignature(false);\r
+                               publicMethod = classInspector.findPublicMethod(javaClassName, \r
+                                                                               methodName, parmTypeNames,\r
+                                                                               primParmTypeNames, isParam, staticMethod, false);\r
+                       }\r
+               }\r
+               catch (ClassNotFoundException e)\r
+               {\r
+                       /* We should always be able to find the class at this point\r
+                        * since the protocol is to check to see if it exists\r
+                        * before checking for a method off of it.  Anyway, just return\r
+                        * null if the class doesn't exist, since the method doesn't\r
+                        * exist in that case.\r
+                        */\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               SanityManager.THROWASSERT("Unexpected exception", e);\r
+                       }\r
+                       return null;\r
+               }\r
+\r
+               return  publicMethod;\r
+       }\r
+\r
+       /**\r
+        * Do code generation for this method call\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class we're generating\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
+               /* If this node is for an ungrouped aggregator, \r
+                * then we generate a conditional\r
+                * wrapper so that we only new the aggregator once.\r
+                *              (fx == null) ? fx = new ... : fx\r
+                */\r
+               LocalField objectFieldLF = null;\r
+               if (singleInstantiation)\r
+               {\r
+                       /* Declare the field */\r
+                       objectFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, javaClassName);\r
+\r
+                       // now we fill in the body of the conditional\r
+\r
+                       mb.getField(objectFieldLF);\r
+                       mb.conditionalIfNull();\r
+               }\r
+\r
+               mb.pushNewStart(javaClassName);\r
+               int nargs = generateParameters(acb, mb);\r
+               mb.pushNewComplete(nargs);\r
+\r
+               if (singleInstantiation) {\r
+\r
+                         mb.putField(objectFieldLF);\r
+                       mb.startElseCode();\r
+                         mb.getField(objectFieldLF);\r
+                       mb.completeConditional();\r
+               }\r
+       }\r
+}\r