001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.RelationalOperator
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.services.compiler.MethodBuilder;
025:
026: import org.apache.derby.iapi.error.StandardException;
027:
028: import org.apache.derby.iapi.sql.compile.Optimizable;
029:
030: import org.apache.derby.iapi.store.access.TransactionController;
031:
032: import org.apache.derby.iapi.types.DataValueDescriptor;
033:
034: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
035:
036: /**
037: * This interface is an abstraction of a relational operator. It was created
038: * for optimization, to allow binary comparison operators and IS NULL to
039: * be treated the same.
040: */
041: public interface RelationalOperator {
042: public final int EQUALS_RELOP = 1;
043: public final int NOT_EQUALS_RELOP = 2;
044: public final int GREATER_THAN_RELOP = 3;
045: public final int GREATER_EQUALS_RELOP = 4;
046: public final int LESS_THAN_RELOP = 5;
047: public final int LESS_EQUALS_RELOP = 6;
048: public final int IS_NULL_RELOP = 7;
049: public final int IS_NOT_NULL_RELOP = 8;
050:
051: /**
052: * Check whether this RelationalOperator is a comparison of the given
053: * column with an expression. If so, return the ColumnReference that
054: * corresponds to the given column, and that is on one side of this
055: * RelationalOperator or the other (this method copes with the
056: * column being on either side of the operator). If the given column
057: * does not appear by itself on one side of the comparison, the
058: * method returns null.
059: *
060: * @param optTable An Optimizable for the base table the column is in
061: * @param columnPosition The ordinal position of the column (one-based)
062: *
063: * @return The ColumnReference on one side of this RelationalOperator
064: * that represents the given columnPosition. Returns null
065: * if no such ColumnReference exists by itself on one side of
066: * this RelationalOperator.
067: */
068: ColumnReference getColumnOperand(Optimizable optTable,
069: int columnPosition);
070:
071: /**
072: * Get the ColumnReference for the given table on one side of this
073: * RelationalOperator. This presumes it will be found only on one
074: * side. If not found, it will return null.
075: */
076: ColumnReference getColumnOperand(Optimizable optTable);
077:
078: /**
079: * Find the operand (left or right) that points to the same table
080: * as the received ColumnReference, and then return either that
081: * operand or the "other" operand, depending on the value of
082: * otherSide. This presumes it will be found only on one
083: * side. If not found, it will return null.
084: *
085: * @param cRef The ColumnReference for which we're searching.
086: * @param refSetSize Size of the referenced map for the predicate
087: * represented by this RelationalOperator node. This is used
088: * for storing base table numbers when searching for cRef.
089: * @param otherSide Assuming we find an operand that points to
090: * the same table as cRef, then we will return the *other*
091: * operand if otherSide is true; else we'll return the operand
092: * that matches cRef.
093: */
094: ValueNode getOperand(ColumnReference cRef, int refSetSize,
095: boolean otherSide);
096:
097: /**
098: * Check whether this RelationalOperator is a comparison of the given
099: * column with an expression. If so, return the expression
100: * the column is being compared to.
101: *
102: * @param tableNumber The table number of the base table the column is in
103: * @param columnPosition The ordinal position of the column (one-based)
104: * @param ft We'll look for the column in all tables at and beneath ft.
105: * This is useful if ft is, say, a ProjectRestrictNode over a subquery--
106: * then we want to look at all of the FROM tables in the subquery to try
107: * to find the right column.
108: *
109: * @return The ValueNode for the expression the column is being compared
110: * to - null if the column is not being compared to anything.
111: */
112: ValueNode getExpressionOperand(int tableNumber, int columnPosition,
113: FromTable ft);
114:
115: /**
116: * Check whether this RelationalOperator is a comparison of the given
117: * column with an expression. If so, generate the Expression for
118: * the ValueNode that the column is being compared to.
119: *
120: * @param optTable An Optimizable for the base table the column is in
121: * @param columnPosition The ordinal position of the column (one-based)
122: * @param acb The ExpressionClassBuilder for the class we're building
123: * @param mb The method the expression will go into
124: *
125: *
126: * @exception StandardException Thrown on error
127: */
128: void generateExpressionOperand(Optimizable optTable,
129: int columnPosition, ExpressionClassBuilder acb,
130: MethodBuilder mb) throws StandardException;
131:
132: /**
133: * Check whether this RelationalOperator compares the given ColumnReference
134: * to any columns in the same table as the ColumnReference.
135: *
136: * @param cr The ColumnReference that is being compared to some
137: * expression.
138: *
139: * @return true if the given ColumnReference is being compared to any
140: * columns from the same table
141: *
142: * @exception StandardException Thrown on error
143: */
144: boolean selfComparison(ColumnReference cr) throws StandardException;
145:
146: /**
147: * Tell whether this relop is a useful start key for the given table.
148: * It has already been determined that the relop has a column from
149: * the given table on one side or the other.
150: *
151: * @param optTable The Optimizable table for which we want to know
152: * whether this is a useful start key.
153: *
154: * @return true if this is a useful start key
155: */
156: boolean usefulStartKey(Optimizable optTable);
157:
158: /**
159: * Tell whether this relop is a useful stop key for the given table.
160: * It has already been determined that the relop has a column from
161: * the given table on one side or the other.
162: *
163: * @param optTable The Optimizable table for which we want to know
164: * whether this is a useful stop key.
165: *
166: * @return true if this is a useful stop key
167: */
168: boolean usefulStopKey(Optimizable optTable);
169:
170: /**
171: * Get the start operator for a scan (at the store level) for this
172: * RelationalOperator.
173: *
174: * @param optTable The optimizable table we're doing the scan on.
175: * This parameter is so we can tell which side of
176: * the operator the table's column is on.
177: *
178: * @return Either ScanController.GT or ScanController.GE
179: *
180: * @see TransactionController#openScan
181: */
182: int getStartOperator(Optimizable optTable);
183:
184: /**
185: * Get the stop operator for a scan (at the store level) for this
186: * RelationalOperator.
187: *
188: * @param optTable The optimizable table we're doing the scan on.
189: * This parameter is so we can tell which side of
190: * the operator the table's column is on.
191: *
192: * @return Either ScanController.GT or ScanController.GE
193: *
194: * @see TransactionController#openScan
195: */
196: int getStopOperator(Optimizable optTable);
197:
198: /**
199: * Generate the absolute column id for the ColumnReference that appears on one
200: * side of this RelationalOperator or the other, and that refers to
201: * the given table. (Absolute column id means column id within the
202: * row stored on disk.)
203: *
204: * @param mb The method the generated code is to go into
205: * @param optTable The optimizable table we're doing the scan on.
206: *
207: */
208: void generateAbsoluteColumnId(MethodBuilder mb, Optimizable optTable);
209:
210: /**
211: * Generate the relative column id for the ColumnReference that appears on one
212: * side of this RelationalOperator or the other, and that refers to
213: * the given table. (Relative column id means column id within the
214: * partial row returned by the store.)
215: *
216: * @param mb The method the generated code is to go into
217: * @param optTable The optimizable table we're doing the scan on.
218: *
219: */
220: void generateRelativeColumnId(MethodBuilder mb, Optimizable optTable);
221:
222: /**
223: * Generate the comparison operator for this RelationalOperator.
224: * The operator can depend on which side of this operator the
225: * optimizable column is.
226: *
227: * @param mb The method the generated code is to go into
228: * @param optTable The optimizable table we're doing the scan on.
229: *
230: */
231: void generateOperator(MethodBuilder mb, Optimizable optTable);
232:
233: /**
234: * Generate the method to evaluate a Qualifier. The factory method for
235: * a Qualifier takes a GeneratedMethod that returns the Orderable
236: * that Qualifier.getOrderable() returns.
237: *
238: * @param acb The ExpressionClassBuilder for the class we're building
239: * @param mb The method the generated code is to go into
240: * @param optTable The Optimizable table the Qualifier will qualify
241: *
242: * @exception StandardException Thrown on error.
243: */
244: void generateQualMethod(ExpressionClassBuilder acb,
245: MethodBuilder mb, Optimizable optTable)
246: throws StandardException;
247:
248: /**
249: * Generate an expression that evaluates to true if this RelationalOperator
250: * uses ordered null semantics, false if it doesn't.
251: *
252: * @param mb The method the generated code is to go into
253: *
254: */
255: void generateOrderedNulls(MethodBuilder mb);
256:
257: /**
258: * Generate an expression that evaluates to true if the result of the
259: * comparison should be negated. For example, col > 1 generates
260: * a comparison operator of <= and a negation of true, while col < 1
261: * generates a comparison operator of < and a negation of false.
262: *
263: * @param mb The method the generated code is to go into
264: * @param optTable The Optimizable table the Qualifier will qualify
265: */
266: void generateNegate(MethodBuilder mb, Optimizable optTable);
267:
268: /** Return true if this operator uses ordered null semantics */
269: boolean orderedNulls();
270:
271: /**
272: * Return true if this operator can be compiled into a Qualifier for
273: * the given Optimizable table. This means that there is a column
274: * from that table on one side of this relop, and an expression that
275: * does not refer to the table on the other side of the relop.
276: *
277: * Note that this method has two uses: 1) see if this operator (or
278: * more specifically, the predicate to which this operator belongs)
279: * can be used as a join predicate (esp. for a hash join), and 2)
280: * see if this operator can be pushed to the target optTable. We
281: * use the parameter "forPush" to distinguish between the two uses
282: * because in some cases (esp. situations where we have subqueries)
283: * the answer to "is this a qualifier?" can differ depending on
284: * whether or not we're pushing. In particular, for binary ops
285: * that are join predicates, if we're just trying to find an
286: * equijoin predicate then this op qualifies if it references either
287: * the target table OR any of the base tables in the table's subtree.
288: * But if we're planning to push the predicate down to the target
289: * table, this op only qualifies if it references the target table
290: * directly. This difference in behavior is required because in
291: * case 1 (searching for join predicates), the operator remains at
292: * its current level in the tree even if its operands reference
293: * nodes further down; in case 2, though, we'll end up pushing
294: * the operator down the tree to child node(s) and that requires
295: * additional logic, such as "scoping" consideration. Until
296: * that logic is in place, we don't search a subtree if the intent
297: * is to push the predicate to which this operator belongs further
298: * down that subtree. See BinaryRelationalOperatorNode for an
299: * example of where this comes into play.
300: *
301: * @param optTable The Optimizable table in question.
302: * @param forPush Are we asking because we're trying to push?
303: *
304: * @return true if this operator can be compiled into a Qualifier
305: * for the given Optimizable table.
306: *
307: * @exception StandardException Thrown on error
308: */
309: boolean isQualifier(Optimizable optTable, boolean forPush)
310: throws StandardException;
311:
312: /**
313: * Return the operator (as an int) for this RelationalOperator.
314: *
315: * @return int The operator for this RelationalOperator.
316: */
317: public int getOperator();
318:
319: /**
320: * Return the variant type for the Qualifier's Orderable.
321: * (Is the Orderable invariant within a scan or within a query?)
322: *
323: * @param optTable The Optimizable table the Qualifier will qualify
324: *
325: * @return int The variant type for the Qualifier's Orderable.
326: * @exception StandardException thrown on error
327: */
328: public int getOrderableVariantType(Optimizable optTable)
329: throws StandardException;
330:
331: /**
332: * Return whether this operator compares the given Optimizable with
333: * a constant whose value is known at compile time.
334: */
335: public boolean compareWithKnownConstant(Optimizable optTable,
336: boolean considerParameters);
337:
338: /**
339: * Return an Object representing the known value that this relational
340: * operator is comparing to a column in the given Optimizable.
341: *
342: * @exception StandardException Thrown on error
343: */
344: public DataValueDescriptor getCompareValue(Optimizable optTable)
345: throws StandardException;
346:
347: /**
348: * Return whether this operator is an equality comparison of the given
349: * optimizable with a constant expression.
350: */
351: public boolean equalsComparisonWithConstantExpression(
352: Optimizable optTable);
353:
354: /**
355: * Return a relational operator which matches the current one
356: * but with the passed in ColumnReference as the (left) operand.
357: *
358: * @param otherCR The ColumnReference for the new (left) operand.
359: *
360: * @return A relational operator which matches the current one
361: * but with the passed in ColumnReference as the (left) operand.
362: *
363: * @exception StandardException Thrown on error
364: */
365: public RelationalOperator getTransitiveSearchClause(
366: ColumnReference otherCR) throws StandardException;
367: }
|