Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / BinaryOperatorNode.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
new file mode 100644 (file)
index 0000000..844a23e
--- /dev/null
@@ -0,0 +1,927 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.BinaryOperatorNode\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.sql.compile.Visitable;\r
+import org.apache.derby.iapi.sql.compile.Visitor;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+\r
+import java.lang.reflect.Modifier;\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.SqlXmlUtil;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.sql.Types;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A BinaryOperatorNode represents a built-in binary operator as defined by\r
+ * the ANSI/ISO SQL standard.  This covers operators like +, -, *, /, =, <, etc.\r
+ * Java operators are not represented here: the JSQL language allows Java\r
+ * methods to be called from expressions, but not Java operators.\r
+ *\r
+ */\r
+\r
+public class BinaryOperatorNode extends ValueNode\r
+{\r
+       String  operator;\r
+       String  methodName;\r
+       ValueNode       receiver; // used in generation\r
+\r
+       /*\r
+       ** These identifiers are used in the grammar.\r
+       */\r
+       public final static int PLUS    = 1;\r
+       public final static int MINUS   = 2;\r
+       public final static int TIMES   = 3;\r
+       public final static int DIVIDE  = 4;\r
+       public final static int CONCATENATE     = 5;\r
+       public final static int EQ      = 6;\r
+       public final static int NE      = 7;\r
+       public final static int GT      = 8;\r
+       public final static int GE      = 9;\r
+       public final static int LT      = 10;\r
+       public final static int LE      = 11;\r
+       public final static int AND     = 12;\r
+       public final static int OR      = 13;\r
+       public final static int LIKE    = 14;\r
+\r
+       ValueNode       leftOperand;\r
+       ValueNode       rightOperand;\r
+\r
+       String          leftInterfaceType;\r
+       String          rightInterfaceType;\r
+       String          resultInterfaceType;\r
+       int                     operatorType;\r
+\r
+       // At the time of adding XML support, it was decided that\r
+       // we should avoid creating new OperatorNodes where possible.\r
+       // So for the XML-related binary operators we just add the\r
+       // necessary code to _this_ class, similar to what is done in\r
+       // TernarnyOperatorNode. Subsequent binary operators (whether\r
+       // XML-related or not) should follow this example when\r
+       // possible.\r
+\r
+       public final static int XMLEXISTS_OP = 0;\r
+       public final static int XMLQUERY_OP = 1;\r
+\r
+       // NOTE: in the following 4 arrays, order\r
+       // IS important.\r
+\r
+       static final String[] BinaryOperators = {\r
+               "xmlexists",\r
+               "xmlquery"\r
+       };\r
+\r
+       static final String[] BinaryMethodNames = {\r
+               "XMLExists",\r
+               "XMLQuery"\r
+       };\r
+\r
+       static final String[] BinaryResultTypes = {\r
+               ClassName.BooleanDataValue,             // XMLExists\r
+               ClassName.XMLDataValue                  // XMLQuery\r
+       };\r
+\r
+       static final String[][] BinaryArgTypes = {\r
+               {ClassName.StringDataValue, ClassName.XMLDataValue},    // XMLExists\r
+               {ClassName.StringDataValue, ClassName.XMLDataValue}             // XMLQuery\r
+       };\r
+\r
+       // Class used to compile an XML query expression and/or load/process\r
+       // XML-specific objects.\r
+       private SqlXmlUtil sqlxUtil;\r
+\r
+       /**\r
+        * Initializer for a BinaryOperatorNode\r
+        *\r
+        * @param leftOperand   The left operand of the node\r
+        * @param rightOperand  The right operand of the node\r
+        * @param operator              The name of the operator\r
+        * @param methodName    The name of the method to call for this operator\r
+        * @param leftInterfaceType     The name of the interface for the left operand\r
+        * @param rightInterfaceType    The name of the interface for the right\r
+        *                                                              operand\r
+        */\r
+\r
+       public void init(\r
+                       Object leftOperand,\r
+                       Object rightOperand,\r
+                       Object operator,\r
+                       Object methodName,\r
+                       Object leftInterfaceType,\r
+                       Object rightInterfaceType)\r
+       {\r
+               this.leftOperand = (ValueNode) leftOperand;\r
+               this.rightOperand = (ValueNode) rightOperand;\r
+               this.operator = (String) operator;\r
+               this.methodName = (String) methodName;\r
+               this.leftInterfaceType = (String) leftInterfaceType;\r
+               this.rightInterfaceType = (String) rightInterfaceType;\r
+               this.operatorType = -1;\r
+       }\r
+\r
+       public void init(\r
+                       Object leftOperand,\r
+                       Object rightOperand,\r
+                       Object leftInterfaceType,\r
+                       Object rightInterfaceType)\r
+       {\r
+               this.leftOperand = (ValueNode) leftOperand;\r
+               this.rightOperand = (ValueNode) rightOperand;\r
+               this.leftInterfaceType = (String) leftInterfaceType;\r
+               this.rightInterfaceType = (String) rightInterfaceType;\r
+               this.operatorType = -1;\r
+       }\r
+\r
+       /**\r
+        * Initializer for a BinaryOperatorNode\r
+        *\r
+        * @param leftOperand   The left operand of the node\r
+        * @param rightOperand  The right operand of the node\r
+        * @param opType  An Integer holding the operatorType\r
+        *  for this operator.\r
+        */\r
+       public void init(\r
+                       Object leftOperand,\r
+                       Object rightOperand,\r
+                       Object opType)\r
+       {\r
+               this.leftOperand = (ValueNode)leftOperand;\r
+               this.rightOperand = (ValueNode)rightOperand;\r
+               this.operatorType = ((Integer)opType).intValue();\r
+               this.operator = BinaryOperators[this.operatorType];\r
+               this.methodName = BinaryMethodNames[this.operatorType];\r
+               this.leftInterfaceType = BinaryArgTypes[this.operatorType][0];\r
+               this.rightInterfaceType = BinaryArgTypes[this.operatorType][1];\r
+               this.resultInterfaceType = BinaryResultTypes[this.operatorType];\r
+       }\r
+\r
+       /**\r
+        * Convert this object to a String.  See comments in QueryTreeNode.java\r
+        * for how this should be done for tree printing.\r
+        *\r
+        * @return      This object as a String\r
+        */\r
+\r
+       public String toString()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       return "operator: " + operator + "\n" +\r
+                               "methodName: " + methodName + "\n" + \r
+                               super.toString();\r
+               }\r
+               else\r
+               {\r
+                       return "";\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Set the operator.\r
+        *\r
+        * @param operator      The operator.\r
+        */\r
+       void setOperator(String operator)\r
+       {\r
+               this.operator = operator;\r
+               this.operatorType = -1;\r
+       }\r
+\r
+       /**\r
+        * Set the methodName.\r
+        *\r
+        * @param methodName    The methodName.\r
+        */\r
+       void setMethodName(String methodName)\r
+       {\r
+               this.methodName = methodName;\r
+               this.operatorType = -1;\r
+       }\r
+\r
+       /**\r
+        * Set the interface type for the left and right arguments.\r
+        * Used when we don't know the interface type until\r
+        * later in binding.\r
+        */\r
+       public void setLeftRightInterfaceType(String iType)\r
+       {\r
+               leftInterfaceType = iType;\r
+               rightInterfaceType = iType;\r
+               this.operatorType = -1;\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
+                       super.printSubNodes(depth);\r
+\r
+                       if (leftOperand != null)\r
+                       {\r
+                               printLabel(depth, "leftOperand: ");\r
+                               leftOperand.treePrint(depth + 1);\r
+                       }\r
+\r
+                       if (rightOperand != null)\r
+                       {\r
+                               printLabel(depth, "rightOperand: ");\r
+                               rightOperand.treePrint(depth + 1);\r
+                       }\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      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
+               leftOperand = leftOperand.bindExpression(fromList, subqueryList, \r
+                       aggregateVector);\r
+               rightOperand = rightOperand.bindExpression(fromList, subqueryList, \r
+                       aggregateVector);\r
+\r
+               if ((operatorType == XMLEXISTS_OP) || (operatorType == XMLQUERY_OP))\r
+                       return bindXMLQuery();\r
+\r
+               /* Is there a ? parameter on the left? */\r
+               if (leftOperand.requiresTypeFromContext())\r
+               {\r
+                       /*\r
+                       ** It's an error if both operands are ? parameters.\r
+                       */\r
+                       if (rightOperand.requiresTypeFromContext())\r
+                       {\r
+                               throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS, \r
+                                                                                                                                       operator);\r
+                       }\r
+\r
+                       /* Set the left operand to the type of right parameter. */\r
+                       leftOperand.setType(rightOperand.getTypeServices());\r
+               }\r
+\r
+               /* Is there a ? parameter on the right? */\r
+               if (rightOperand.requiresTypeFromContext())\r
+               {\r
+                       /* Set the right operand to the type of the left parameter. */\r
+                       rightOperand.setType(leftOperand.getTypeServices());\r
+               }\r
+\r
+               return genSQLJavaSQLTree();\r
+       }\r
+\r
+    /**\r
+     * Bind an XMLEXISTS or XMLQUERY operator.  Makes sure\r
+     * the operand type and target type are both correct\r
+     * and sets the result type.\r
+     *\r
+     * @exception StandardException Thrown on error\r
+     */\r
+    public ValueNode bindXMLQuery()\r
+        throws StandardException\r
+    {\r
+        // Check operand types.\r
+        TypeId leftOperandType = leftOperand.getTypeId();\r
+        TypeId rightOperandType = rightOperand.getTypeId();\r
+\r
+        // Left operand is query expression and must be a string\r
+        // literal.  SQL/XML spec doesn't allow params nor expressions\r
+        // 6.17: <XQuery expression> ::= <character string literal> \r
+        if (!(leftOperand instanceof CharConstantNode))\r
+        {\r
+            throw StandardException.newException(\r
+                SQLState.LANG_INVALID_XML_QUERY_EXPRESSION);\r
+        }\r
+        else {\r
+        // compile the query expression.\r
+            sqlxUtil = new SqlXmlUtil();\r
+            sqlxUtil.compileXQExpr(\r
+                ((CharConstantNode)leftOperand).getString(),\r
+                (operatorType == XMLEXISTS_OP ? "XMLEXISTS" : "XMLQUERY"));\r
+        }\r
+\r
+        // Right operand must be an XML data value.  NOTE: This\r
+        // is a Derby-specific restriction, not an SQL/XML one.\r
+        // We have this restriction because the query engine\r
+        // that we use (currently Xalan) cannot handle non-XML\r
+        // context items.\r
+        if ((rightOperandType != null) &&\r
+            !rightOperandType.isXMLTypeId())\r
+        {\r
+            throw StandardException.newException(\r
+                SQLState.LANG_INVALID_CONTEXT_ITEM_TYPE,\r
+                rightOperandType.getSQLTypeName());\r
+        }\r
+\r
+        // Is there a ? parameter on the right?\r
+        if (rightOperand.requiresTypeFromContext())\r
+        {\r
+            // For now, since JDBC has no type defined for XML, we\r
+            // don't allow binding to an XML parameter.\r
+            throw StandardException.newException(\r
+                SQLState.LANG_ATTEMPT_TO_BIND_XML);\r
+        }\r
+\r
+        // Set the result type of this operator.\r
+        if (operatorType == XMLEXISTS_OP) {\r
+        // For XMLEXISTS, the result type is always SQLBoolean.\r
+        // The "true" in the next line says that the result\r
+        // can be nullable--which it can be if evaluation of\r
+        // the expression returns a null (this is per SQL/XML\r
+        // spec, 8.4)\r
+            setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true));\r
+        }\r
+        else {\r
+        // The result of an XMLQUERY operator is always another\r
+        // XML data value, per SQL/XML spec 6.17: "...yielding a value\r
+        // X1 of an XML type."\r
+            setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor(\r
+                StoredFormatIds.XML_TYPE_ID));\r
+        }\r
+\r
+        return genSQLJavaSQLTree();\r
+    }\r
+\r
+       /** generate a SQL->Java->SQL conversion tree above the left and right\r
+        * operand of this Binary Operator Node if needed. Subclasses can override\r
+        * the default behavior.\r
+        */\r
+       public ValueNode genSQLJavaSQLTree() throws StandardException\r
+       {\r
+               TypeId leftTypeId = leftOperand.getTypeId();\r
+               \r
+               if (leftTypeId.userType())\r
+                       leftOperand = leftOperand.genSQLJavaSQLTree();\r
+\r
+               TypeId rightTypeId = rightOperand.getTypeId();\r
+               if (rightTypeId.userType())\r
+                       rightOperand = rightOperand.genSQLJavaSQLTree();\r
+\r
+               return this;\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
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode preprocess(int numTables,\r
+                                                               FromList outerFromList,\r
+                                                               SubqueryList outerSubqueryList,\r
+                                                               PredicateList outerPredicateList) \r
+                                       throws StandardException\r
+       {\r
+               leftOperand = leftOperand.preprocess(numTables,\r
+                                                                                        outerFromList, outerSubqueryList,\r
+                                                                                        outerPredicateList);\r
+               rightOperand = rightOperand.preprocess(numTables,\r
+                                                                                          outerFromList, outerSubqueryList,\r
+                                                                                          outerPredicateList);\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Do code generation for this binary operator.\r
+        *\r
+        * @param acb   The ExpressionClassBuilder for the class we're generating\r
+        * @param mb    The method the code to place the code\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 BinaryOperatorNode was created as a part of an IN-list\r
+                * "probe predicate" then we do not want to generate the relational\r
+                * operator itself; instead we want to generate the underlying\r
+                * IN-list for which this operator node was created.\r
+                *\r
+                * We'll get here in situations where the optimizer chooses a plan\r
+                * for which the probe predicate is *not* a useful start/stop key\r
+                * and thus is not being used for execution-time index probing.\r
+                * In this case we are effectively "reverting" the probe predicate\r
+                * back to the InListOperatorNode from which it was created.  Or put\r
+                * another way, we are "giving up" on index multi-probing and simply\r
+                * generating the original IN-list as a regular restriction.\r
+                */\r
+               if (this instanceof BinaryRelationalOperatorNode)\r
+               {\r
+                       InListOperatorNode ilon =\r
+                               ((BinaryRelationalOperatorNode)this).getInListOp();\r
+\r
+                       if (ilon != null)\r
+                       {\r
+                               ilon.generateExpression(acb, mb);\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               String          resultTypeName;\r
+               String          receiverType;\r
+\r
+/*\r
+** if i have a operator.getOrderableType() == constant, then just cache \r
+** it in a field.  if i have QUERY_INVARIANT, then it would be good to\r
+** cache it in something that is initialized each execution,\r
+** but how?\r
+*/\r
+\r
+               // If we're dealing with XMLEXISTS or XMLQUERY, there is some\r
+               // additional work to be done.\r
+               boolean xmlGen =\r
+                       (operatorType == XMLQUERY_OP) || (operatorType == XMLEXISTS_OP);\r
+\r
+               if (xmlGen) {\r
+               // We create an execution-time object so that we can retrieve\r
+               // saved objects (esp. our compiled query expression) from\r
+               // the activation.  We do this for two reasons: 1) this level\r
+               // of indirection allows us to separate the XML data type\r
+               // from the required XML implementation classes (esp. JAXP\r
+               // and Xalan classes)--for more on how this works, see the\r
+               // comments in SqlXmlUtil.java; and 2) we can take\r
+               // the XML query expression, which we've already compiled,\r
+               // and pass it to the execution-time object for each row,\r
+               // which means that we only have to compile the query\r
+               // expression once per SQL statement (instead of once per\r
+               // row); see SqlXmlExecutor.java for more.\r
+                       mb.pushNewStart(\r
+                               "org.apache.derby.impl.sql.execute.SqlXmlExecutor");\r
+                       mb.pushNewComplete(addXmlOpMethodParams(acb, mb));\r
+               }\r
+\r
+               /*\r
+               ** The receiver is the operand with the higher type precedence.\r
+               ** Like always makes the left the receiver.\r
+               **\r
+               */\r
+               if (leftOperand.getTypeId().typePrecedence() >\r
+                       rightOperand.getTypeId().typePrecedence())\r
+               {\r
+                       receiver = leftOperand;\r
+                       /*\r
+                       ** let the receiver type be determined by an\r
+                       ** overridable method so that if methods are\r
+                       ** not implemented on the lowest interface of\r
+                       ** a class, they can note that in the implementation\r
+                       ** of the node that uses the method.\r
+                       */\r
+                   receiverType = (operatorType == -1)\r
+                               ? getReceiverInterfaceName()\r
+                               : leftInterfaceType;\r
+\r
+                       /*\r
+                       ** Generate (with <left expression> only being evaluated once)\r
+                       **\r
+                       **      <left expression>.method(<left expression>, <right expression>...)\r
+                       */\r
+\r
+                       leftOperand.generateExpression(acb, mb);\r
+                       mb.cast(receiverType); // cast the method instance\r
+                       // stack: left\r
+                       \r
+                       mb.dup();\r
+                       mb.cast(leftInterfaceType);\r
+                       // stack: left, left\r
+                       \r
+                       rightOperand.generateExpression(acb, mb);\r
+                       mb.cast(rightInterfaceType); // second arg with cast\r
+                       // stack: left, left, right\r
+               }\r
+               else\r
+               {\r
+                       receiver = rightOperand;\r
+                       /*\r
+                       ** let the receiver type be determined by an\r
+                       ** overridable method so that if methods are\r
+                       ** not implemented on the lowest interface of\r
+                       ** a class, they can note that in the implementation\r
+                       ** of the node that uses the method.\r
+                       */\r
+                   receiverType = (operatorType == -1)\r
+                               ? getReceiverInterfaceName()\r
+                               : rightInterfaceType;\r
+\r
+                       /*\r
+                       ** Generate (with <right expression> only being evaluated once)\r
+                       **\r
+                       **      <right expression>.method(<left expression>, <right expression>)\r
+                       **\r
+                       ** UNLESS we're generating an XML operator such as XMLEXISTS.\r
+                       ** In that case we want to generate\r
+                       ** \r
+                       **  SqlXmlExecutor.method(left, right)"\r
+                       **\r
+                       ** and we've already pushed the SqlXmlExecutor object to\r
+                       ** the stack.\r
+                       */\r
+\r
+                       rightOperand.generateExpression(acb, mb);                       \r
+                       mb.cast(receiverType); // cast the method instance\r
+                       // stack: right\r
+                       \r
+                       if (!xmlGen) {\r
+                               mb.dup();\r
+                               mb.cast(rightInterfaceType);\r
+                               // stack: right,right\r
+                       }\r
+                       \r
+                       leftOperand.generateExpression(acb, mb);\r
+                       mb.cast(leftInterfaceType); // second arg with cast\r
+                       // stack: right,right,left\r
+                       \r
+                       mb.swap();\r
+                       // stack: right,left,right                      \r
+               }\r
+\r
+               /* Figure out the result type name */\r
+               resultTypeName = (operatorType == -1)\r
+                       ? getTypeCompiler().interfaceName()\r
+                       : resultInterfaceType;\r
+\r
+               // Boolean return types don't need a result field\r
+               boolean needField = !getTypeId().isBooleanTypeId();\r
+\r
+               if (needField) {\r
+\r
+                       /* Allocate an object for re-use to hold the result of the operator */\r
+                       LocalField resultField =\r
+                               acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);\r
+\r
+                       /*\r
+                       ** Call the method for this operator.\r
+                       */\r
+                       mb.getField(resultField); // third arg\r
+                       //following method is special code for concatenation where if field is null, we want it to be initialized to NULL SQLxxx type object\r
+                       //before generating code "field = method(p1, p2, field);"\r
+                       initializeResultField(acb, mb, resultField);\r
+\r
+                       /* pass statically calculated scale to decimal divide method to make\r
+                        * result set scale consistent, beetle 3901\r
+                        */\r
+                       int jdbcType;\r
+                       if ((getTypeServices() != null) &&\r
+                               ((jdbcType = getTypeServices().getJDBCTypeId()) == java.sql.Types.DECIMAL ||\r
+                                jdbcType == java.sql.Types.NUMERIC) &&\r
+                               operator.equals("/"))\r
+                       {\r
+                               mb.push(getTypeServices().getScale());          // 4th arg\r
+                               mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 4);\r
+                       }\r
+                       else if (xmlGen) {\r
+                       // This is for an XMLQUERY operation, so invoke the method\r
+                       // on our execution-time object.\r
+                               mb.callMethod(VMOpcode.INVOKEVIRTUAL, null,\r
+                                       methodName, resultTypeName, 3);\r
+                       }\r
+                       else\r
+                               mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 3);\r
+\r
+                       //the need for following if was realized while fixing bug 5704 where decimal*decimal was resulting an overflow value but we were not detecting it\r
+                       if (getTypeId().variableLength())//since result type is numeric variable length, generate setWidth code.\r
+                       {\r
+                               if (getTypeId().isNumericTypeId())\r
+                               {\r
+                                       // to leave the DataValueDescriptor value on the stack, since setWidth is void\r
+                                       mb.dup();\r
+\r
+                                       mb.push(getTypeServices().getPrecision());\r
+                                       mb.push(getTypeServices().getScale());\r
+                                       mb.push(true);\r
+                                       mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3);\r
+                               }\r
+                       }\r
+\r
+\r
+                       /*\r
+                       ** Store the result of the method call in the field, so we can re-use\r
+                       ** the object.\r
+                       */\r
+\r
+                       mb.putField(resultField);\r
+               } else {\r
+                       if (xmlGen) {\r
+                       // This is for an XMLEXISTS operation, so invoke the method\r
+                       // on our execution-time object.\r
+                               mb.callMethod(VMOpcode.INVOKEVIRTUAL, null,\r
+                                       methodName, resultTypeName, 2);\r
+                       }\r
+                       else {\r
+                               mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType,\r
+                                       methodName, resultTypeName, 2);\r
+                       }\r
+               }\r
+       }\r
+\r
+       //following method is no-op here but in concatenation node, this method is used to check if resultField is null,\r
+       //and if yes, then we want it to be initialized to NULL SQLxxx type object\r
+       protected void initializeResultField(ExpressionClassBuilder acb, MethodBuilder mb, LocalField resultField)\r
+       throws StandardException\r
+       {\r
+       }\r
+\r
+       /**\r
+        * Set the leftOperand to the specified ValueNode\r
+        *\r
+        * @param newLeftOperand        The new leftOperand\r
+        */\r
+       public void setLeftOperand(ValueNode newLeftOperand)\r
+       {\r
+               leftOperand = newLeftOperand;\r
+       }\r
+\r
+       /**\r
+        * Get the leftOperand\r
+        *\r
+        * @return The current leftOperand.\r
+        */\r
+       public ValueNode getLeftOperand()\r
+       {\r
+               return leftOperand;\r
+       }\r
+\r
+       /**\r
+        * Set the rightOperand to the specified ValueNode\r
+        *\r
+        * @param newRightOperand       The new rightOperand\r
+        */\r
+       public void setRightOperand(ValueNode newRightOperand)\r
+       {\r
+               rightOperand = newRightOperand;\r
+       }\r
+\r
+       /**\r
+        * Get the rightOperand\r
+        *\r
+        * @return The current rightOperand.\r
+        */\r
+       public ValueNode getRightOperand()\r
+       {\r
+               return rightOperand;\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
+               boolean pushable;\r
+               pushable = leftOperand.categorize(referencedTabs, simplePredsOnly);\r
+               pushable = (rightOperand.categorize(referencedTabs, simplePredsOnly) && pushable);\r
+               return pushable;\r
+       }\r
+\r
+       /**\r
+        * Remap all ColumnReferences in this tree to be clones of the\r
+        * underlying expression.\r
+        *\r
+        * @return ValueNode                    The remapped expression tree.\r
+        *\r
+        * @exception StandardException                 Thrown on error\r
+        */\r
+       public ValueNode remapColumnReferencesToExpressions()\r
+               throws StandardException\r
+       {\r
+               leftOperand = leftOperand.remapColumnReferencesToExpressions();\r
+               rightOperand = rightOperand.remapColumnReferencesToExpressions();\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 (leftOperand.isConstantExpression() &&\r
+                               rightOperand.isConstantExpression());\r
+       }\r
+\r
+       /** @see ValueNode#constantExpression */\r
+       public boolean constantExpression(PredicateList whereClause)\r
+       {\r
+               return (leftOperand.constantExpression(whereClause) &&\r
+                               rightOperand.constantExpression(whereClause));\r
+       }\r
+\r
+       /**\r
+        * Determine the type the binary method is called on.\r
+        * By default, based on the receiver.\r
+        *\r
+        * Override in nodes that use methods on super-interfaces of\r
+        * the receiver's interface, such as comparisons.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public String getReceiverInterfaceName() throws StandardException {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(receiver!=null,"can't get receiver interface name until receiver is set");\r
+               }\r
+\r
+               return receiver.getTypeCompiler().interfaceName();\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                        - immutable\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
+               int leftType = leftOperand.getOrderableVariantType();\r
+               int rightType = rightOperand.getOrderableVariantType();\r
+\r
+               return Math.min(leftType, rightType);\r
+       }\r
+\r
+       /**\r
+        * Swap the left and right sides.\r
+        */\r
+       void swapOperands()\r
+       {\r
+               String    tmpInterfaceType = leftInterfaceType;\r
+               ValueNode tmpVN = leftOperand;\r
+\r
+               leftOperand = rightOperand;\r
+               rightOperand = tmpVN;\r
+               leftInterfaceType = rightInterfaceType;\r
+               rightInterfaceType = tmpInterfaceType;\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 (leftOperand != null && !v.stopTraversal())\r
+               {\r
+                       leftOperand = (ValueNode)leftOperand.accept(v);\r
+               }\r
+\r
+               if (rightOperand != null && !v.stopTraversal())\r
+               {\r
+                       rightOperand = (ValueNode)rightOperand.accept(v);\r
+               }\r
+               \r
+               return returnNode;\r
+       }\r
+\r
+        /**\r
+         * @inheritDoc\r
+         */\r
+        protected boolean isEquivalent(ValueNode o) throws StandardException\r
+        {\r
+               if (!isSameNodeType(o))\r
+               {\r
+                       return false;\r
+               }\r
+               BinaryOperatorNode other = (BinaryOperatorNode)o;\r
+               return methodName.equals(other.methodName)\r
+                      && leftOperand.isEquivalent(other.leftOperand)\r
+                      && rightOperand.isEquivalent(other.rightOperand);\r
+        }\r
+\r
+       /**\r
+        * Push the fields necessary to generate an instance of\r
+        * SqlXmlExecutor, which will then be used at execution\r
+        * time to retrieve the compiled XML query expression,\r
+        * along with any other XML-specific objects.\r
+        *\r
+        * @param acb The ExpressionClassBuilder for the class we're generating\r
+        * @param mb  The method the code to place the code\r
+        *\r
+        * @return The number of items that this method pushed onto\r
+        *  the mb's stack.\r
+        */\r
+       private int addXmlOpMethodParams(ExpressionClassBuilder acb,\r
+               MethodBuilder mb) throws StandardException\r
+       {\r
+               // Push activation so that we can get our saved object\r
+               // (which will hold the compiled XML query expression)\r
+               // back at execute time.\r
+               acb.pushThisAsActivation(mb);\r
+\r
+               // Push our saved object (the compiled query and XML-specific\r
+               // objects).\r
+               mb.push(getCompilerContext().addSavedObject(sqlxUtil));\r
+\r
+               // We pushed 2 items to the stack.\r
+               return 2;\r
+       }\r
+}\r