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 / NonStaticMethodCallNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/NonStaticMethodCallNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/NonStaticMethodCallNode.java
new file mode 100644 (file)
index 0000000..48d01fd
--- /dev/null
@@ -0,0 +1,493 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.NonStaticMethodCallNode\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.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+\r
+import org.apache.derby.iapi.sql.compile.Visitable;\r
+import org.apache.derby.iapi.sql.compile.Visitor;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import org.apache.derby.iapi.services.loader.ClassInspector;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.types.JSQLType;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+import org.apache.derby.iapi.error.ExceptionSeverity;\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import org.apache.derby.catalog.AliasInfo;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A NonStaticMethodCallNode is really a node to represent a (static or non-static)\r
+ * method call from an object (as opposed to a static method call from a class.\r
+ */\r
+public class NonStaticMethodCallNode extends MethodCallNode\r
+{\r
+       /*\r
+       ** The receiver for a non-static method call is an object, represented\r
+       ** by a ValueNode.\r
+       */\r
+       JavaValueNode   receiver;       \r
+\r
+       /* Is this a static method call? Assume non-static call */\r
+       private boolean isStatic;\r
+\r
+       /**\r
+        * Initializer for a NonStaticMethodCallNode\r
+        *\r
+        * @param methodName    The name of the method to call\r
+        * @param receiver              A JavaValueNode representing the receiving object\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void init(\r
+                                                       Object methodName,\r
+                                                       Object receiver)\r
+                       throws StandardException\r
+       {\r
+               super.init(methodName);\r
+\r
+               /*\r
+               ** If the receiver is a Java value that has been converted to a\r
+               ** SQL value, get rid of the conversion and just use the Java value\r
+               ** as-is.  If the receiver is a "normal" SQL value, then convert\r
+               ** it to a Java value to use as the receiver.\r
+               */\r
+               if (receiver instanceof JavaToSQLValueNode)\r
+               {\r
+                       this.receiver = ((JavaToSQLValueNode) receiver).\r
+                                                                               getJavaValueNode();\r
+               }\r
+               else\r
+               {\r
+                       this.receiver = (JavaValueNode) getNodeFactory().\r
+                                                               getNode(\r
+                                                                       C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,\r
+                                                                       receiver,\r
+                                                                       getContextManager());\r
+//            System.out.println("NonStaticMethodCallNode.init() receiver = "+receiver);\r
+// get nulpointer because not .bind?\r
+//            System.out.println("\ttypecompiler = "+((ValueNode)receiver).getTypeCompiler());\r
+//            System.out.println("\tdtd = "+((ValueNode)receiver).getTypeServices());\r
+//            System.out.println("\ttypeid = "+((ValueNode)receiver).getTypeServices().getTypeId());\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 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
+               boolean         nullParameter = false;\r
+               String[]        parmTypeNames;\r
+\r
+               /* NULL and ? not allowed as receivers */\r
+               if (receiver instanceof SQLToJavaValueNode)\r
+               {\r
+                       ValueNode       SQLValue =\r
+                                                       ((SQLToJavaValueNode) receiver).getSQLValueNode();\r
+\r
+                       if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(!(SQLValue instanceof UntypedNullConstantNode),\r
+                               "UntypedNullConstantNode found as a receiver of a non-static method call");\r
+\r
+                       //\r
+                       //      We don't allow methods off of naked unnamed "?" parameters.\r
+                       //      This is because we have no way of knowing the data type of\r
+                       //      a naked "?" parameter.\r
+                       //\r
+                       //      However, if this "?" has actually been associated with a\r
+                       //      named "?paramName" parameter in a COPY PUBLICATION statement,\r
+                       //      then we have a type for it. Binding can continue.\r
+                       //\r
+\r
+                       if (SQLValue.requiresTypeFromContext())\r
+                       {\r
+                               if ( SQLValue.getTypeServices() == null )\r
+                               { throw StandardException.newException(SQLState.LANG_PARAMETER_RECEIVER, methodName); }\r
+                       }\r
+               }\r
+\r
+               bindParameters(fromList, subqueryList, aggregateVector);\r
+\r
+               /* Now we don't allow an alias static method call here (that has to\r
+                * use :: sign for any static call).  If it gets here, it can't be\r
+                * alias static method call.\r
+                */\r
+               receiver = receiver.bindExpression(fromList, subqueryList, aggregateVector);\r
+\r
+        // Don't allow LOB types to be used as a method receiver\r
+        String type = receiver.getJSQLType().getSQLType().getTypeId().getSQLTypeName();\r
+        if ( type.equals("BLOB") || type.equals("CLOB") || type.equals("NCLOB") ) {\r
+            throw StandardException.newException(SQLState.LOB_AS_METHOD_ARGUMENT_OR_RECEIVER);\r
+        }\r
+\r
+               javaClassName = receiver.getJavaTypeName();\r
+\r
+               /* Not allowed to use a primitive type as a method receiver */\r
+               if (ClassInspector.primitiveType(javaClassName))\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_PRIMITIVE_RECEIVER, methodName, javaClassName);\r
+               }\r
+\r
+               /* Resolve the method call */\r
+               resolveMethodCall(javaClassName, false);\r
+\r
+               /* Remember if method is static */\r
+               isStatic = Modifier.isStatic(method.getModifiers());\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 method calls 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
+               if (receiver != null)\r
+               {\r
+                       pushable = pushable && receiver.categorize(referencedTabs, simplePredsOnly);\r
+               }\r
+\r
+               return pushable;\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
+        *                                                        (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() throws StandardException\r
+       {\r
+               int receiverVariant = receiver.getOrderableVariantType();\r
+\r
+               if (receiverVariant > Qualifier.SCAN_INVARIANT) {\r
+                       \r
+                       // If the method call is related to a trigger then the return\r
+                       // values are SCAN_INVARIANT even though their calls look QUERY_INVARIANT\r
+                       // because they take no parameters.\r
+                       if (receiver.getJavaTypeName().equals("org.apache.derby.iapi.db.TriggerExecutionContext"))\r
+                               receiverVariant = Qualifier.SCAN_INVARIANT;\r
+               }\r
+\r
+\r
+               int thisVariant = super.getOrderableVariantType();\r
+               if (receiverVariant < thisVariant)      //return the more variant one\r
+                       return receiverVariant;\r
+               return thisVariant;\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
+               if (receiver != null)\r
+               {\r
+                       receiver.remapColumnReferencesToExpressions();\r
+               }\r
+\r
+               return super.remapColumnReferencesToExpressions();\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 (receiver != null)\r
+                       {\r
+                               printLabel(depth, "receiver :");\r
+                               receiver.treePrint(depth + 1);\r
+                       }\r
+               }\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
+               super.preprocess(numTables,\r
+                                                outerFromList, outerSubqueryList,\r
+                                                outerPredicateList);\r
+               receiver.preprocess(numTables,\r
+                                                       outerFromList, outerSubqueryList,\r
+                                                       outerPredicateList);\r
+\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
+               boolean inConditional = false;\r
+               /*\r
+               ** If this method returns its value to the Java domain,\r
+               ** generate the receiver and put the value in a field (only if\r
+               ** this method does not return a primitive type).  If it\r
+               ** returns its value to the SQL domain, it's up to the JavaToSQLNode\r
+               ** to call generateReceiver().\r
+               **\r
+               ** Also, don't do this if the return value from this method\r
+               ** call will be discarded.  This is the case for a CALL statement.\r
+               ** One reason we don't want to do this for a CALL statement\r
+               ** is that the ?: operator cannot be made into a statement.\r
+               */\r
+               if ( ( ! valueReturnedToSQLDomain()) && ( ! returnValueDiscarded()))\r
+               {\r
+                       if (generateReceiver(acb, mb, receiver))\r
+                       {\r
+                               /*\r
+                               ** If the above did generate the expression, let's test it for\r
+                               ** a null value.\r
+                               */\r
+                               /*\r
+                               ** Generate the following to test for null:\r
+                               **\r
+                               **              (receiverExpression == null) ?\r
+                               */\r
+\r
+                               inConditional = true;\r
+                               mb.conditionalIfNull();\r
+                               mb.pushNull(getJavaTypeName());\r
+                               mb.startElseCode();\r
+                       }\r
+               }\r
+\r
+               /*\r
+               ** Generate the following:\r
+               **\r
+               ** <receiver>.<method name>(<param> (, <param> )* )\r
+               **\r
+               ** for non-static calls.\r
+               **\r
+               ** Refer to the field holding the receiver, if there is any.\r
+               */\r
+\r
+               Class declaringClass = method.getDeclaringClass();\r
+               \r
+               /*\r
+               ** If it's an interface, generate an interface method call, if it's a static,\r
+               ** generate a static method call, otherwise generate a regular method call.\r
+               */\r
+\r
+               short methodType;\r
+\r
+               if (declaringClass.isInterface())\r
+                       methodType = VMOpcode.INVOKEINTERFACE;\r
+               else if (isStatic)\r
+                       methodType = VMOpcode.INVOKESTATIC;\r
+               else\r
+                       methodType = VMOpcode.INVOKEVIRTUAL;\r
+\r
+               getReceiverExpression(acb, mb, receiver);\r
+               if (isStatic)\r
+                       mb.endStatement(); // PUSHCOMPILER ???\r
+\r
+               int nargs = generateParameters(acb, mb);\r
+\r
+               mb.callMethod(methodType, declaringClass.getName(), methodName, getJavaTypeName(), nargs);\r
+\r
+               if (inConditional)\r
+                       mb.completeConditional();\r
+       }\r
+\r
+       /**\r
+        * Generate the expression that evaluates to the receiver. This is\r
+        * for the case where a java expression is being returned to the SQL\r
+        * domain, and we need to check whether the receiver is null (if so,\r
+        * the SQL value should be set to null, and this Java expression\r
+        * not evaluated). Instance method calls and field references have\r
+        * receivers, while class method calls and calls to constructors do\r
+        * not. If this Java expression does not have a receiver, this method\r
+        * returns null.\r
+        *\r
+        * Only generate the receiver once and cache it in a field. This is\r
+        * because there will be two references to the receiver, and we want\r
+        * to evaluate it only once.\r
+        *\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class being built\r
+        * @param mb    The method the expression will go into\r
+        *\r
+        * @return              true if compiled receiver, false otherwise.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       protected boolean generateReceiver(ExpressionClassBuilder acb,\r
+                                                                                       MethodBuilder mb)\r
+                                                                       throws StandardException\r
+       {\r
+               /*\r
+               ** Let's pretend that a call to a static method doesn't have a\r
+               ** receiver, since the method call is actually to the class,\r
+               ** and can be made even if the receiver is null (that is, we\r
+               ** always want to call a static method, even if the receiver is null).\r
+               */\r
+               if (isStatic)\r
+                       return false;\r
+               \r
+               return generateReceiver(acb, mb, receiver);\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
+               if (v.skipChildren(this))\r
+               {\r
+                       return v.visit(this);\r
+               }\r
+\r
+               Visitable returnNode = super.accept(v);\r
+\r
+               if (receiver != null && !v.stopTraversal())\r
+               {\r
+                       receiver = (JavaValueNode)receiver.accept(v);\r
+               }\r
+\r
+               return returnNode;\r
+       }\r
+}\r