--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.RelationalOperator\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.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.compile.Optimizable;\r
+\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+/**\r
+ * This interface is an abstraction of a relational operator. It was created\r
+ * for optimization, to allow binary comparison operators and IS NULL to\r
+ * be treated the same.\r
+ */\r
+public interface RelationalOperator\r
+{\r
+ public final int EQUALS_RELOP = 1;\r
+ public final int NOT_EQUALS_RELOP = 2;\r
+ public final int GREATER_THAN_RELOP = 3;\r
+ public final int GREATER_EQUALS_RELOP = 4;\r
+ public final int LESS_THAN_RELOP = 5;\r
+ public final int LESS_EQUALS_RELOP = 6;\r
+ public final int IS_NULL_RELOP = 7;\r
+ public final int IS_NOT_NULL_RELOP = 8;\r
+\r
+ /**\r
+ * Check whether this RelationalOperator is a comparison of the given\r
+ * column with an expression. If so, return the ColumnReference that\r
+ * corresponds to the given column, and that is on one side of this\r
+ * RelationalOperator or the other (this method copes with the\r
+ * column being on either side of the operator). If the given column\r
+ * does not appear by itself on one side of the comparison, the\r
+ * method returns null.\r
+ *\r
+ * @param optTable An Optimizable for the base table the column is in\r
+ * @param columnPosition The ordinal position of the column (one-based)\r
+ *\r
+ * @return The ColumnReference on one side of this RelationalOperator\r
+ * that represents the given columnPosition. Returns null\r
+ * if no such ColumnReference exists by itself on one side of\r
+ * this RelationalOperator.\r
+ */\r
+ ColumnReference getColumnOperand(Optimizable optTable, int columnPosition);\r
+\r
+ /**\r
+ * Get the ColumnReference for the given table on one side of this\r
+ * RelationalOperator. This presumes it will be found only on one\r
+ * side. If not found, it will return null.\r
+ */\r
+ ColumnReference getColumnOperand(Optimizable optTable);\r
+\r
+ /**\r
+ * Find the operand (left or right) that points to the same table\r
+ * as the received ColumnReference, and then return either that\r
+ * operand or the "other" operand, depending on the value of\r
+ * otherSide. This presumes it will be found only on one\r
+ * side. If not found, it will return null.\r
+ *\r
+ * @param cRef The ColumnReference for which we're searching.\r
+ * @param refSetSize Size of the referenced map for the predicate\r
+ * represented by this RelationalOperator node. This is used\r
+ * for storing base table numbers when searching for cRef.\r
+ * @param otherSide Assuming we find an operand that points to\r
+ * the same table as cRef, then we will return the *other*\r
+ * operand if otherSide is true; else we'll return the operand\r
+ * that matches cRef.\r
+ */\r
+ ValueNode getOperand(ColumnReference cRef, int refSetSize,\r
+ boolean otherSide);\r
+\r
+ /**\r
+ * Check whether this RelationalOperator is a comparison of the given\r
+ * column with an expression. If so, return the expression\r
+ * the column is being compared to.\r
+ *\r
+ * @param tableNumber The table number of the base table the column is in\r
+ * @param columnPosition The ordinal position of the column (one-based)\r
+ * @param ft We'll look for the column in all tables at and beneath ft.\r
+ * This is useful if ft is, say, a ProjectRestrictNode over a subquery--\r
+ * then we want to look at all of the FROM tables in the subquery to try\r
+ * to find the right column.\r
+ *\r
+ * @return The ValueNode for the expression the column is being compared\r
+ * to - null if the column is not being compared to anything.\r
+ */\r
+ ValueNode getExpressionOperand(int tableNumber,\r
+ int columnPosition,\r
+ FromTable ft);\r
+\r
+ /**\r
+ * Check whether this RelationalOperator is a comparison of the given\r
+ * column with an expression. If so, generate the Expression for\r
+ * the ValueNode that the column is being compared to.\r
+ *\r
+ * @param optTable An Optimizable for the base table the column is in\r
+ * @param columnPosition The ordinal position of the column (one-based)\r
+ * @param acb The ExpressionClassBuilder for the class we're building\r
+ * @param mb The method the expression will go into\r
+ *\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ void generateExpressionOperand(Optimizable optTable,\r
+ int columnPosition,\r
+ ExpressionClassBuilder acb,\r
+ MethodBuilder mb)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Check whether this RelationalOperator compares the given ColumnReference\r
+ * to any columns in the same table as the ColumnReference.\r
+ *\r
+ * @param cr The ColumnReference that is being compared to some\r
+ * expression.\r
+ *\r
+ * @return true if the given ColumnReference is being compared to any\r
+ * columns from the same table\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ boolean selfComparison(ColumnReference cr)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Tell whether this relop is a useful start key for the given table.\r
+ * It has already been determined that the relop has a column from\r
+ * the given table on one side or the other.\r
+ *\r
+ * @param optTable The Optimizable table for which we want to know\r
+ * whether this is a useful start key.\r
+ *\r
+ * @return true if this is a useful start key\r
+ */\r
+ boolean usefulStartKey(Optimizable optTable);\r
+\r
+ /**\r
+ * Tell whether this relop is a useful stop key for the given table.\r
+ * It has already been determined that the relop has a column from\r
+ * the given table on one side or the other.\r
+ *\r
+ * @param optTable The Optimizable table for which we want to know\r
+ * whether this is a useful stop key.\r
+ *\r
+ * @return true if this is a useful stop key\r
+ */\r
+ boolean usefulStopKey(Optimizable optTable);\r
+\r
+ /**\r
+ * Get the start operator for a scan (at the store level) for this\r
+ * RelationalOperator.\r
+ *\r
+ * @param optTable The optimizable table we're doing the scan on.\r
+ * This parameter is so we can tell which side of\r
+ * the operator the table's column is on.\r
+ *\r
+ * @return Either ScanController.GT or ScanController.GE\r
+ *\r
+ * @see TransactionController#openScan\r
+ */\r
+ int getStartOperator(Optimizable optTable);\r
+\r
+ /**\r
+ * Get the stop operator for a scan (at the store level) for this\r
+ * RelationalOperator.\r
+ *\r
+ * @param optTable The optimizable table we're doing the scan on.\r
+ * This parameter is so we can tell which side of\r
+ * the operator the table's column is on.\r
+ *\r
+ * @return Either ScanController.GT or ScanController.GE\r
+ *\r
+ * @see TransactionController#openScan\r
+ */\r
+ int getStopOperator(Optimizable optTable);\r
+\r
+ /**\r
+ * Generate the absolute column id for the ColumnReference that appears on one\r
+ * side of this RelationalOperator or the other, and that refers to\r
+ * the given table. (Absolute column id means column id within the \r
+ * row stored on disk.)\r
+ *\r
+ * @param mb The method the generated code is to go into\r
+ * @param optTable The optimizable table we're doing the scan on.\r
+ *\r
+ */\r
+ void generateAbsoluteColumnId(MethodBuilder mb,\r
+ Optimizable optTable);\r
+\r
+ /**\r
+ * Generate the relative column id for the ColumnReference that appears on one\r
+ * side of this RelationalOperator or the other, and that refers to\r
+ * the given table. (Relative column id means column id within the \r
+ * partial row returned by the store.)\r
+ *\r
+ * @param mb The method the generated code is to go into\r
+ * @param optTable The optimizable table we're doing the scan on.\r
+ *\r
+ */\r
+ void generateRelativeColumnId(MethodBuilder mb,\r
+ Optimizable optTable);\r
+\r
+ /**\r
+ * Generate the comparison operator for this RelationalOperator.\r
+ * The operator can depend on which side of this operator the\r
+ * optimizable column is.\r
+ * \r
+ * @param mb The method the generated code is to go into\r
+ * @param optTable The optimizable table we're doing the scan on.\r
+ *\r
+ */\r
+ void generateOperator(MethodBuilder mb,\r
+ Optimizable optTable);\r
+\r
+ /**\r
+ * Generate the method to evaluate a Qualifier. The factory method for\r
+ * a Qualifier takes a GeneratedMethod that returns the Orderable\r
+ * that Qualifier.getOrderable() returns.\r
+ *\r
+ * @param acb The ExpressionClassBuilder for the class we're building\r
+ * @param mb The method the generated code is to go into\r
+ * @param optTable The Optimizable table the Qualifier will qualify\r
+ *\r
+ * @exception StandardException Thrown on error.\r
+ */\r
+ void generateQualMethod(ExpressionClassBuilder acb,\r
+ MethodBuilder mb,\r
+ Optimizable optTable)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Generate an expression that evaluates to true if this RelationalOperator\r
+ * uses ordered null semantics, false if it doesn't.\r
+ *\r
+ * @param mb The method the generated code is to go into\r
+ *\r
+ */\r
+ void generateOrderedNulls(MethodBuilder mb);\r
+\r
+ /**\r
+ * Generate an expression that evaluates to true if the result of the\r
+ * comparison should be negated. For example, col > 1 generates\r
+ * a comparison operator of <= and a negation of true, while col < 1\r
+ * generates a comparison operator of < and a negation of false.\r
+ *\r
+ * @param mb The method the generated code is to go into\r
+ * @param optTable The Optimizable table the Qualifier will qualify\r
+ */\r
+ void generateNegate(MethodBuilder mb,\r
+ Optimizable optTable);\r
+\r
+ /** Return true if this operator uses ordered null semantics */\r
+ boolean orderedNulls();\r
+\r
+ /**\r
+ * Return true if this operator can be compiled into a Qualifier for\r
+ * the given Optimizable table. This means that there is a column\r
+ * from that table on one side of this relop, and an expression that\r
+ * does not refer to the table on the other side of the relop.\r
+ *\r
+ * Note that this method has two uses: 1) see if this operator (or\r
+ * more specifically, the predicate to which this operator belongs)\r
+ * can be used as a join predicate (esp. for a hash join), and 2)\r
+ * see if this operator can be pushed to the target optTable. We\r
+ * use the parameter "forPush" to distinguish between the two uses\r
+ * because in some cases (esp. situations where we have subqueries)\r
+ * the answer to "is this a qualifier?" can differ depending on\r
+ * whether or not we're pushing. In particular, for binary ops\r
+ * that are join predicates, if we're just trying to find an\r
+ * equijoin predicate then this op qualifies if it references either\r
+ * the target table OR any of the base tables in the table's subtree.\r
+ * But if we're planning to push the predicate down to the target\r
+ * table, this op only qualifies if it references the target table\r
+ * directly. This difference in behavior is required because in\r
+ * case 1 (searching for join predicates), the operator remains at\r
+ * its current level in the tree even if its operands reference\r
+ * nodes further down; in case 2, though, we'll end up pushing\r
+ * the operator down the tree to child node(s) and that requires\r
+ * additional logic, such as "scoping" consideration. Until\r
+ * that logic is in place, we don't search a subtree if the intent\r
+ * is to push the predicate to which this operator belongs further\r
+ * down that subtree. See BinaryRelationalOperatorNode for an\r
+ * example of where this comes into play.\r
+ *\r
+ * @param optTable The Optimizable table in question.\r
+ * @param forPush Are we asking because we're trying to push?\r
+ *\r
+ * @return true if this operator can be compiled into a Qualifier\r
+ * for the given Optimizable table.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ boolean isQualifier(Optimizable optTable, boolean forPush)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Return the operator (as an int) for this RelationalOperator.\r
+ *\r
+ * @return int The operator for this RelationalOperator.\r
+ */\r
+ public int getOperator();\r
+\r
+ /**\r
+ * Return the variant type for the Qualifier's Orderable.\r
+ * (Is the Orderable invariant within a scan or within a query?)\r
+ *\r
+ * @param optTable The Optimizable table the Qualifier will qualify\r
+ *\r
+ * @return int The variant type for the Qualifier's Orderable.\r
+ * @exception StandardException thrown on error\r
+ */\r
+ public int getOrderableVariantType(Optimizable optTable)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Return whether this operator compares the given Optimizable with\r
+ * a constant whose value is known at compile time.\r
+ */\r
+ public boolean compareWithKnownConstant(Optimizable optTable, boolean considerParameters);\r
+\r
+ /**\r
+ * Return an Object representing the known value that this relational\r
+ * operator is comparing to a column in the given Optimizable.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public DataValueDescriptor getCompareValue(Optimizable optTable)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Return whether this operator is an equality comparison of the given\r
+ * optimizable with a constant expression.\r
+ */\r
+ public boolean equalsComparisonWithConstantExpression(Optimizable optTable);\r
+\r
+ /**\r
+ * Return a relational operator which matches the current one\r
+ * but with the passed in ColumnReference as the (left) operand.\r
+ *\r
+ * @param otherCR The ColumnReference for the new (left) operand.\r
+ *\r
+ * @return A relational operator which matches the current one\r
+ * but with the passed in ColumnReference as the (left) operand.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public RelationalOperator getTransitiveSearchClause(ColumnReference otherCR)\r
+ throws StandardException;\r
+}\r