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 / BinaryComparisonOperatorNode.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/BinaryComparisonOperatorNode.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/BinaryComparisonOperatorNode.java
new file mode 100644 (file)
index 0000000..66bfa44
--- /dev/null
@@ -0,0 +1,424 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.BinaryComparisonOperatorNode\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.C_NodeTypes;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+\r
+import org.apache.derby.iapi.sql.compile.TypeCompiler;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import java.util.Vector;\r
+import java.sql.Types;\r
+\r
+/**\r
+ * This node is the superclass  for all binary comparison operators, such as =,\r
+ * <>, <, etc.\r
+ *\r
+ */\r
+\r
+public abstract class BinaryComparisonOperatorNode extends BinaryOperatorNode\r
+{\r
+       // Use between selectivity?\r
+       private boolean forQueryRewrite;\r
+       private boolean betweenSelectivity;\r
+\r
+       /**\r
+        * Initializer for a BinaryComparisonOperatorNode\r
+        *\r
+        * @param leftOperand   The left operand of the comparison\r
+        * @param rightOperand  The right operand of the comparison\r
+        * @param operator              The name of the operator\r
+        * @param methodName    The name of the method to call in the generated\r
+        *                                              class\r
+        */\r
+\r
+       public void init(\r
+                               Object  leftOperand,\r
+                               Object  rightOperand,\r
+                               Object          operator,\r
+                               Object          methodName)\r
+       {\r
+               super.init(leftOperand, rightOperand, operator, methodName,\r
+                               ClassName.DataValueDescriptor, ClassName.DataValueDescriptor);\r
+       }\r
+\r
+       /**\r
+        * This node was generated as part of a query rewrite. Bypass the\r
+        * normal comparability checks.\r
+        * @param val  true if this was for a query rewrite\r
+        */\r
+       public void setForQueryRewrite(boolean val)\r
+       {\r
+               forQueryRewrite=val;\r
+       }\r
+\r
+       /**\r
+        * Was this node generated in a query rewrite?\r
+        *\r
+        * @return  true if it was generated in a query rewrite.\r
+        */\r
+       public boolean getForQueryRewrite()\r
+       {\r
+               return forQueryRewrite;\r
+       }\r
+\r
+       /**\r
+        * Use between selectivity when calculating the selectivity.\r
+        */\r
+       void setBetweenSelectivity()\r
+       {\r
+               betweenSelectivity = true;\r
+       }\r
+\r
+       /**\r
+        * Return whether or not to use the between selectivity for this node.\r
+        *\r
+        * @return Whether or not to use the between selectivity for this node.\r
+        */\r
+       boolean getBetweenSelectivity()\r
+       {\r
+               return betweenSelectivity;\r
+       }\r
+\r
+\r
+       /**\r
+        * Bind this comparison operator.  All that has to be done for binding\r
+        * a comparison operator is to bind the operands, check the compatibility\r
+        * of the types, and set the result type to SQLBoolean.\r
+        *\r
+        * @param fromList                      The query's FROM list\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
+               super.bindExpression(fromList, subqueryList, aggregateVector);\r
+\r
+               TypeCompiler leftTC = leftOperand.getTypeCompiler();\r
+               TypeCompiler rightTC = rightOperand.getTypeCompiler();\r
+               TypeId leftTypeId = leftOperand.getTypeId();\r
+               TypeId rightTypeId = rightOperand.getTypeId();\r
+\r
+               /*\r
+                * If we are comparing a non-string with a string type, then we\r
+                * must prevent the non-string value from being used to probe into\r
+                * an index on a string column. This is because the string types\r
+                * are all of low precedence, so the comparison rules of the non-string\r
+                * value are used, so it may not find values in a string index because\r
+                * it will be in the wrong order. So, cast the string value to its\r
+                * own type. This is easier than casting it to the non-string type,\r
+                * because we would have to figure out the right length to cast it to.\r
+                */\r
+               if (! leftTypeId.isStringTypeId() && rightTypeId.isStringTypeId())\r
+               {\r
+                       DataTypeDescriptor rightTypeServices = rightOperand.getTypeServices();\r
+\r
+                       rightOperand =  (ValueNode)\r
+                               getNodeFactory().getNode(\r
+                                       C_NodeTypes.CAST_NODE,\r
+                                       rightOperand, \r
+                                       new DataTypeDescriptor(\r
+                                                       rightTypeId,\r
+                                                       true, \r
+                                                       rightTypeServices.getMaximumWidth()),\r
+                                       getContextManager());\r
+                       ((CastNode) rightOperand).bindCastNodeOnly();\r
+               }\r
+               else if (! rightTypeId.isStringTypeId() && leftTypeId.isStringTypeId())\r
+               {\r
+                       DataTypeDescriptor leftTypeServices = leftOperand.getTypeServices();\r
+\r
+                       leftOperand =  (ValueNode)\r
+                               getNodeFactory().getNode(\r
+                                       C_NodeTypes.CAST_NODE,\r
+                                       leftOperand, \r
+                                       new DataTypeDescriptor(\r
+                                                       leftTypeId,\r
+                                                       true, \r
+                                                       leftTypeServices.getMaximumWidth()),\r
+                                       getContextManager());\r
+                       ((CastNode) leftOperand).bindCastNodeOnly();\r
+               }\r
+\r
+               /* Test type compatability and set type info for this node */\r
+               bindComparisonOperator();\r
+\r
+               return this;\r
+       }\r
+\r
+\r
+       /**\r
+        * Test the type compatability of the operands and set the type info\r
+        * for this node.  This method is useful both during binding and\r
+        * when we generate nodes within the language module outside of the parser.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void bindComparisonOperator()\r
+                       throws StandardException\r
+       {\r
+               TypeId  leftType;\r
+               TypeId  rightType;\r
+               boolean                         nullableResult;\r
+\r
+               leftType = leftOperand.getTypeId();\r
+               rightType = rightOperand.getTypeId();\r
+\r
+\r
+               /*\r
+               ** Can the types be compared to each other?  If not, throw an\r
+               ** exception.\r
+               */\r
+               boolean forEquals = operator.equals("=") || operator.equals("<>");\r
+\r
+        boolean cmp = leftOperand.getTypeServices().comparable(\r
+                       rightOperand.getTypeServices(),\r
+                               forEquals,\r
+                               getClassFactory());\r
+               // Bypass the comparable check if this is a rewrite from the \r
+               // optimizer.  We will assume Mr. Optimizer knows what he is doing.\r
+          if (!cmp && !forQueryRewrite) {\r
+                       throw StandardException.newException(SQLState.LANG_NOT_COMPARABLE, \r
+                                       leftOperand.getTypeServices().getSQLTypeNameWithCollation() ,\r
+                                       rightOperand.getTypeServices().getSQLTypeNameWithCollation());\r
+                               \r
+                 }\r
+\r
+               \r
+               /*\r
+               ** Set the result type of this comparison operator based on the\r
+               ** operands.  The result type is always SQLBoolean - the only question\r
+               ** is whether it is nullable or not.  If either of the operands is\r
+               ** nullable, the result of the comparison must be nullable, too, so\r
+               ** we can represent the unknown truth value.\r
+               */\r
+               nullableResult = leftOperand.getTypeServices().isNullable() ||\r
+                                                       rightOperand.getTypeServices().isNullable();\r
+               setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, nullableResult));\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
+        * @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
+\r
+               /* This is where we start to consider flattening expression subqueries based\r
+                * on a uniqueness condition.  If the right child is a SubqueryNode then\r
+                * it is a potentially flattenable expression subquery.  If we flatten the\r
+                * subquery then we at least need to change the right operand of this \r
+                * comparison.  However, we may want to push the comparison into the subquery\r
+                * itself and replace this outer comparison with TRUE in the tree.  Thus we\r
+                * return rightOperand.preprocess() if the rightOperand is a SubqueryNode.\r
+                * NOTE: SubqueryNode.preprocess() is smart enough to return this node\r
+                * if it is not flattenable.\r
+                * NOTE: We only do this if the subquery has not yet been preprocessed.\r
+                * (A subquery can get preprocessed multiple times if it is a child node\r
+                * in an expression that gets transformed, like BETWEEN.  The subquery\r
+                * remembers whether or not it has been preprocessed and simply returns if\r
+                * it has already been preprocessed.  The return returns the SubqueryNode,\r
+                * so an invalid tree is returned if we set the parent comparison operator\r
+                * when the subquery has already been preprocessed.)\r
+                */\r
+               if ((rightOperand instanceof SubqueryNode) &&\r
+                       !((SubqueryNode) rightOperand).getPreprocessed())\r
+               {\r
+                       ((SubqueryNode) rightOperand).setParentComparisonOperator(this);\r
+                       return rightOperand.preprocess(numTables,\r
+                                                                                  outerFromList, outerSubqueryList,\r
+                                                                                  outerPredicateList);\r
+               }\r
+               else\r
+               {\r
+                       rightOperand = rightOperand.preprocess(numTables,\r
+                                                                                                  outerFromList, outerSubqueryList,\r
+                                                                                                  outerPredicateList);\r
+                       return this;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Eliminate NotNodes in the current query block.  We traverse the tree, \r
+        * inverting ANDs and ORs and eliminating NOTs as we go.  We stop at \r
+        * ComparisonOperators and boolean expressions.  We invert \r
+        * ComparisonOperators and replace boolean expressions with \r
+        * boolean expression = false.\r
+        * NOTE: Since we do not recurse under ComparisonOperators, there\r
+        * still could be NotNodes left in the tree.\r
+        *\r
+        * @param       underNotNode            Whether or not we are under a NotNode.\r
+        *                                                      \r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       ValueNode eliminateNots(boolean underNotNode) \r
+                                       throws StandardException\r
+       {\r
+               if (! underNotNode)\r
+               {\r
+                       return this;\r
+               }\r
+\r
+               /* Convert the BinaryComparison operator to its negation */\r
+               return getNegation(leftOperand, rightOperand);\r
+       }\r
+\r
+       /**\r
+        * Negate the comparison.\r
+        *\r
+        * @param leftOperand   The left operand of the comparison operator\r
+        * @param rightOperand  The right operand of the comparison operator\r
+        *\r
+        * @return BinaryOperatorNode   The negated expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       BinaryOperatorNode getNegation(ValueNode leftOperand,\r
+                                                                                 ValueNode rightOperand)\r
+                               throws StandardException\r
+       {\r
+               /* Keep the compiler happy - this method should never be called.\r
+                * We should always be calling the method in a sub-class.\r
+                */\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(false,\r
+                                       "expected to call getNegation() for subclass " +\r
+                                       getClass().toString());\r
+               return this;\r
+       }\r
+\r
+       /**\r
+        * Finish putting an expression into conjunctive normal\r
+        * form.  An expression tree in conjunctive normal form meets\r
+        * the following criteria:\r
+        *              o  If the expression tree is not null,\r
+        *                 the top level will be a chain of AndNodes terminating\r
+        *                 in a true BooleanConstantNode.\r
+        *              o  The left child of an AndNode will never be an AndNode.\r
+        *              o  Any right-linked chain that includes an AndNode will\r
+        *                 be entirely composed of AndNodes terminated by a true BooleanConstantNode.\r
+        *              o  The left child of an OrNode will never be an OrNode.\r
+        *              o  Any right-linked chain that includes an OrNode will\r
+        *                 be entirely composed of OrNodes terminated by a false BooleanConstantNode.\r
+        *              o  ValueNodes other than AndNodes and OrNodes are considered\r
+        *                 leaf nodes for purposes of expression normalization.\r
+        *                 In other words, we won't do any normalization under\r
+        *                 those nodes.\r
+        *\r
+        * In addition, we track whether or not we are under a top level AndNode.  \r
+        * SubqueryNodes need to know this for subquery flattening.\r
+        *\r
+        * @param       underTopAndNode         Whether or not we are under a top level AndNode.\r
+        *                                                      \r
+        *\r
+        * @return              The modified expression\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public ValueNode changeToCNF(boolean underTopAndNode) \r
+                                       throws StandardException\r
+       {\r
+               /* If our right child is a subquery and we are under a top and node\r
+                * then we want to mark the subquery as under a top and node.\r
+                * That will allow us to consider flattening it.\r
+                */\r
+               if (underTopAndNode && (rightOperand instanceof SubqueryNode))\r
+               {\r
+                       rightOperand = rightOperand.changeToCNF(underTopAndNode);\r
+               }\r
+\r
+               return this;\r
+       }\r
+       \r
+       /** @see BinaryOperatorNode#genSQLJavaSQLTree */\r
+       public ValueNode genSQLJavaSQLTree() throws StandardException\r
+       {\r
+               TypeId leftTypeId = leftOperand.getTypeId();\r
+\r
+               /* If I have Java types, I need only add java->sql->java if the types\r
+                * are not comparable \r
+                */\r
+               if (leftTypeId.userType())\r
+               {\r
+                       if (leftOperand.getTypeServices().comparable(leftOperand.getTypeServices(),\r
+                                       false, getClassFactory()))\r
+                               return this;\r
+\r
+                       leftOperand = leftOperand.genSQLJavaSQLTree();\r
+               }\r
+\r
+               TypeId rightTypeId = rightOperand.getTypeId();\r
+\r
+               if (rightTypeId.userType())\r
+               {\r
+                       if (rightOperand.getTypeServices().comparable(rightOperand.getTypeServices(),\r
+                                       false, getClassFactory()))\r
+                               return this;\r
+\r
+                       rightOperand = rightOperand.genSQLJavaSQLTree();\r
+               }\r
+\r
+               return this;\r
+       }\r
+}\r