001: /*
002:
003: Derby - Class org.apache.derby.iapi.sql.compile.Optimizable
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.iapi.sql.compile;
023:
024: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
025: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
026: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
027:
028: import org.apache.derby.iapi.error.StandardException;
029:
030: import org.apache.derby.iapi.util.JBitSet;
031:
032: import java.util.Properties;
033:
034: /**
035: * Optimizable provides services for optimizing a table in a query.
036: */
037:
038: public interface Optimizable {
039:
040: /**
041: * Choose the next access path to evaluate for this Optimizable.
042: *
043: * @param optimizer Optimizer to use.
044: * @param predList The predicate list for this optimizable.
045: * The optimizer always passes null, and it is up
046: * to the optimizable object to pass along its
047: * own predicate list, if appropriate, when delegating
048: * this method.
049: * @param rowOrdering The row ordering for all the outer tables in
050: * the join order. This method will add the ordering
051: * of the next access path to the given RowOrdering.
052: *
053: * @return true means another access path was chosen, false means
054: * no more access paths to evaluate.
055: *
056: * @exception StandardException Thrown on error
057: */
058: boolean nextAccessPath(Optimizer optimizer,
059: OptimizablePredicateList predList, RowOrdering rowOrdering)
060: throws StandardException;
061:
062: /**
063: * Choose the best access path for this Optimizable.
064: *
065: * @param optimizer Optimizer to use.
066: * @param predList The predicate list to optimize against
067: * @param outerCost The CostEstimate for the outer tables in the join order,
068: * telling how many times this Optimizable will be scanned.
069: * @param rowOrdering The row ordering for all the tables in the
070: * join order, including this one.
071: *
072: * @return The optimizer's estimated cost of the best access path.
073: *
074: * @exception StandardException Thrown on error
075: */
076: CostEstimate optimizeIt(Optimizer optimizer,
077: OptimizablePredicateList predList, CostEstimate outerCost,
078: RowOrdering rowOrdering) throws StandardException;
079:
080: /**
081: * Get the current access path under consideration for this Optimizable
082: */
083: AccessPath getCurrentAccessPath();
084:
085: /**
086: * Get the best access path for this Optimizable.
087: */
088: AccessPath getBestAccessPath();
089:
090: /**
091: * Get the best sort-avoidance path for this Optimizable.
092: */
093: AccessPath getBestSortAvoidancePath();
094:
095: /**
096: * Get the best access path overall for this Optimizable.
097: */
098: AccessPath getTrulyTheBestAccessPath();
099:
100: /**
101: * Mark this optimizable so that its sort avoidance path will be
102: * considered.
103: */
104: void rememberSortAvoidancePath();
105:
106: /**
107: * Check whether this optimizable's sort avoidance path should
108: * be considered.
109: */
110: boolean considerSortAvoidancePath();
111:
112: /**
113: * Remember the current join strategy as the best one so far in this
114: * join order.
115: */
116: void rememberJoinStrategyAsBest(AccessPath ap);
117:
118: /**
119: * Get the table descriptor for this table (if any). Only base tables
120: * have table descriptors - for the rest of the optimizables, this
121: * method returns null.
122: */
123: TableDescriptor getTableDescriptor();
124:
125: /**
126: * Get the map of referenced tables for this Optimizable.
127: *
128: * @return JBitSet Referenced table map.
129: */
130: JBitSet getReferencedTableMap();
131:
132: /**
133: * Push an OptimizablePredicate down, if this node accepts it.
134: *
135: * @param optimizablePredicate OptimizablePredicate to push down.
136: *
137: * @return Whether or not the predicate was pushed down.
138: *
139: * @exception StandardException Thrown on error
140: */
141: boolean pushOptPredicate(OptimizablePredicate optimizablePredicate)
142: throws StandardException;
143:
144: /**
145: * Pull all the OptimizablePredicates from this Optimizable and put them
146: * in the given OptimizablePredicateList.
147: *
148: * @param optimizablePredicates The list to put the pulled predicates
149: * in.
150: *
151: * @exception StandardException Thrown on error
152: */
153: void pullOptPredicates(
154: OptimizablePredicateList optimizablePredicates)
155: throws StandardException;
156:
157: /**
158: * Modify the access path for this Optimizable, as necessary. This includes
159: * things like adding a result set to translate from index rows to base rows
160: *
161: * @param outerTables Bit map of the tables that are outer to this one
162: * in the join order.
163: *
164: * @return The (potentially new) Optimizable at the top of the tree.
165: *
166: * @exception StandardException Thrown on error
167: */
168: Optimizable modifyAccessPath(JBitSet outerTables)
169: throws StandardException;
170:
171: /**
172: * Return whether or not this is a covering index. We expect to call this
173: * during generation, after access path selection is complete.
174: *
175: * @param cd ConglomerateDesriptor for index to consider
176: *
177: * @return boolean Whether or not this is a covering index.
178: *
179: * @exception StandardException Thrown on error
180: */
181: public boolean isCoveringIndex(ConglomerateDescriptor cd)
182: throws StandardException;
183:
184: /**
185: * Get the Properties list, if any, associated with this optimizable.
186: *
187: * @return The Properties list, if any, associated with this optimizable.
188: */
189: public Properties getProperties();
190:
191: /**
192: * Set the Properties list for this optimizalbe.
193: *
194: * @param tableProperties The Properties list for this optimizable.
195: */
196: public void setProperties(Properties tableProperties);
197:
198: /**
199: * Verify that the Properties list with optimizer overrides, if specified, is valid
200: *
201: * @param dDictionary The DataDictionary to use.
202: *
203: * @exception StandardException Thrown on error
204: */
205: public void verifyProperties(DataDictionary dDictionary)
206: throws StandardException;
207:
208: /**
209: * Get the (exposed) name of this Optimizable
210: *
211: * @return The name of this Optimizable.
212: * @exception StandardException Thrown on error
213: */
214: public String getName() throws StandardException;
215:
216: /**
217: * Get the table name of this Optimizable. Only base tables have
218: * table names (by the time we use this method, all views will have
219: * been resolved).
220: */
221: public String getBaseTableName();
222:
223: /**
224: * Convert an absolute to a relative 0-based column position.
225: * This is useful when generating qualifiers for partial rows
226: * from the store.
227: *
228: * @param absolutePosition The absolute 0-based column position for the column.
229: *
230: * @return The relative 0-based column position for the column.
231: */
232: public int convertAbsoluteToRelativeColumnPosition(
233: int absolutePosition);
234:
235: /**
236: * When remembering "truly the best" access path for an Optimizable, we
237: * have to keep track of which OptimizerImpl the "truly the best" access
238: * is for. In most queries there will only be one OptimizerImpl in
239: * question, but in cases where there are nested subqueries, there will be
240: * one OptimizerImpl for every level of nesting, and each OptimizerImpl
241: * might have its own idea of what this Optimizable's "truly the best path"
242: * access path really is. In addition, there could be Optimizables
243: * above this Optimizable that might need to override the best path
244: * chosen during optimization. So whenever we save a "truly the best" path,
245: * we take note of which Optimizer/Optimizable told us to do so. Then
246: * as each level of subquery finishes optimization, the corresponding
247: * OptimizerImpl/Optimizable can load its preferred access path into this
248: * Optimizable's trulyTheBestAccessPath field and pass it up the tree, until
249: * eventually the outer-most OptimizerImpl can choose to either use the best
250: * path that it received from below (by calling "rememberAsBest()") or else
251: * use the path that it found to be "best" for itself.
252: *
253: * This method is what allows us to keep track of which OptimizerImpl or
254: * Optimizable saved which "best plan", and allows us to load the
255: * appropriate plans after each round of optimization.
256: *
257: * @param action Indicates whether we're adding, loading, or removing
258: * a best plan for the OptimizerImpl/Optimizable.
259: * @param planKey Object to use as the map key when adding/looking up
260: * a plan. If it is an instance of OptimizerImpl then it corresponds
261: * to an outer query; otherwise it's some Optimizable above this
262: * Optimizable that could potentially reject plans chosen by the
263: * OptimizerImpl to which this Optimizable belongs.
264: */
265: public void updateBestPlanMap(short action, Object planKey)
266: throws StandardException;
267:
268: /**
269: * Remember the current access path as the best one (so far).
270: *
271: * @param planType The type of plan (one of Optimizer.NORMAL_PLAN
272: * or Optimizer.SORT_AVOIDANCE_PLAN)
273: * @param optimizer The OptimizerImpl that is telling this Optimizable
274: * to remember its current path as "truly the best".
275: *
276: * @exception StandardException thrown on error.
277: */
278: public void rememberAsBest(int planType, Optimizer optimizer)
279: throws StandardException;
280:
281: /**
282: * Begin the optimization process for this Optimizable. This can be
283: * called many times for an Optimizable while optimizing a query -
284: * it will typically be called every time the Optimizable is placed
285: * in a potential join order.
286: */
287: public void startOptimizing(Optimizer optimizer,
288: RowOrdering rowOrdering);
289:
290: /**
291: * Estimate the cost of scanning this Optimizable using the given
292: * predicate list with the given conglomerate. It is assumed that the
293: * predicate list has already been classified. This cost estimate is
294: * just for one scan, not for the life of the query.
295: *
296: * @see OptimizablePredicateList#classify
297: *
298: * @param predList The predicate list to optimize against
299: * @param cd The conglomerate descriptor to get the cost of
300: * @param outerCost The estimated cost of the part of the plan outer
301: * to this optimizable.
302: * @param optimizer The optimizer to use to help estimate the cost
303: * @param rowOrdering The row ordering for all the tables in the
304: * join order, including this one.
305: *
306: * @return The estimated cost of doing the scan
307: *
308: * @exception StandardException Thrown on error
309: */
310: CostEstimate estimateCost(OptimizablePredicateList predList,
311: ConglomerateDescriptor cd, CostEstimate outerCost,
312: Optimizer optimizer, RowOrdering rowOrdering)
313: throws StandardException;
314:
315: /** Tell whether this Optimizable represents a base table */
316: boolean isBaseTable();
317:
318: /** Tell whether this Optimizable is materializable
319: *
320: * @exception StandardException Thrown on error
321: */
322: boolean isMaterializable() throws StandardException;
323:
324: /** Tell whether this Optimizable can be instantiated multiple times */
325: boolean supportsMultipleInstantiations();
326:
327: /** Get this Optimizable's result set number */
328: int getResultSetNumber();
329:
330: /** Get this Optimizable's table number */
331: int getTableNumber();
332:
333: /** Return true if this Optimizable has a table number */
334: boolean hasTableNumber();
335:
336: /** Return true if this is the target table of an update */
337: public boolean forUpdate();
338:
339: /** Return the initial capacity of the hash table, for hash join strategy */
340: public int initialCapacity();
341:
342: /** Return the load factor of the hash table, for hash join strategy */
343: public float loadFactor();
344:
345: /** Return the hash key column numbers, for hash join strategy */
346: public int[] hashKeyColumns();
347:
348: /** Set the hash key column numbers, for hash join strategy */
349: public void setHashKeyColumns(int[] columnNumbers);
350:
351: /**
352: * Is the current proposed join strategy for this optimizable feasible
353: * given the predicate list?
354: *
355: * @param predList The predicate list that has been pushed down to
356: * this optimizable
357: * @param optimizer The optimizer to use.
358: *
359: * @return true means feasible
360: *
361: * @exception StandardException Thrown on error
362: */
363: public boolean feasibleJoinStrategy(
364: OptimizablePredicateList predList, Optimizer optimizer)
365: throws StandardException;
366:
367: /**
368: * @param rowCount
369: * @param maxMemoryPerTable
370: * @return true if the memory usage of the proposed access path is OK, false if not.
371: *
372: * @exception StandardException standard error policy
373: */
374: public boolean memoryUsageOK(double rowCount, int maxMemoryPerTable)
375: throws StandardException;
376:
377: /**
378: * Return the maximum capacity of the hash table, for hash join strategy
379: *
380: * @param maxMemoryPerTable The maximum number of bytes to be used. Ignored if the user has set a maximum
381: * number of rows for the Optimizable.
382: *
383: * @exception StandardException Standard error policy
384: */
385: public int maxCapacity(JoinStrategy joinStrategy,
386: int maxMemoryPerTable) throws StandardException;
387:
388: /**
389: * Can this Optimizable appear at the current location in the join order.
390: * In other words, have the Optimizable's dependencies been satisfied?
391: *
392: * @param assignedTableMap The tables that have been placed so far in the join order.
393: *
394: * @return Where or not this Optimizable can appear at the current location in the join order.
395: */
396: public boolean legalJoinOrder(JBitSet assignedTableMap);
397:
398: /**
399: * Get the DataDictionary from this Optimizable. This is useful for code generation
400: * because we need to get the constraint name if scanning a back index so that
401: * RunTimeStatistics can display the correct info.
402: *
403: * @return The DataDictionary to use.
404: *
405: * @exception StandardException Thrown on error
406: */
407: public DataDictionary getDataDictionary() throws StandardException;
408:
409: /**
410: * Is the optimizable the target table of an update or delete?
411: *
412: * @return Whether or not the optimizable the target table of an update or delete.
413: */
414: public boolean isTargetTable();
415:
416: /**
417: * Get the number of the number of columns returned by this Optimizable.
418: *
419: * @return The number of the number of columns returned by this Optimizable.
420: */
421: public int getNumColumnsReturned();
422:
423: /**
424: * Will the optimizable return at most 1 row per scan?
425: *
426: * @return Whether or not the optimizable will return at most 1 row per scan?
427: *
428: * @exception StandardException Thrown on error
429: */
430: public boolean isOneRowScan() throws StandardException;
431:
432: /**
433: * Init the access paths for this optimizable.
434: *
435: * @param optimizer The optimizer being used.
436: */
437: public void initAccessPaths(Optimizer optimizer);
438:
439: /**
440: * Does this optimizable have a uniqueness condition on the
441: * given predicate list, and if so, how many unique keys will be
442: * returned per scan.
443: *
444: * @param predList The predicate list to check
445: *
446: * @return <= 0 means there is no uniqueness condition
447: * > 0 means there is a uniqueness condition,
448: * and the return value is the number of rows per scan.
449: *
450: * @exception StandardException Thrown on error
451: */
452: public double uniqueJoin(OptimizablePredicateList predList)
453: throws StandardException;
454: }
|