KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > SingleChildResultSetNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.SingleChildResultSetNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.services.context.ContextManager;
25
26 import org.apache.derby.iapi.sql.compile.AccessPath;
27 import org.apache.derby.iapi.sql.compile.CostEstimate;
28 import org.apache.derby.iapi.sql.compile.Optimizable;
29 import org.apache.derby.iapi.sql.compile.OptimizableList;
30 import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
31 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
32 import org.apache.derby.iapi.sql.compile.Optimizer;
33 import org.apache.derby.iapi.sql.compile.Visitable;
34 import org.apache.derby.iapi.sql.compile.Visitor;
35 import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
36 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
37
38 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
39 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
40
41 import org.apache.derby.iapi.sql.Activation;
42 import org.apache.derby.iapi.sql.ResultSet;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
47
48 import org.apache.derby.iapi.services.sanity.SanityManager;
49
50 import org.apache.derby.iapi.util.JBitSet;
51
52 import java.util.Properties JavaDoc;
53 import java.util.Vector JavaDoc;
54
55 /**
56  * A SingleChildResultSetNode represents a result set with a single child.
57  *
58  * @author Jerry Brenner
59  */

60
61 abstract class SingleChildResultSetNode extends FromTable
62 {
63     /**
64      * ResultSetNode under the SingleChildResultSetNode
65      */

66     ResultSetNode childResult;
67
68     // Does this node have the truly... for the underlying tree
69
protected boolean hasTrulyTheBestAccessPath;
70
71
72     /**
73      * Initialilzer for a SingleChildResultSetNode.
74      *
75      * @param childResult The child ResultSetNode
76      * @param tableProperties Properties list associated with the table
77      */

78
79     public void init(Object JavaDoc childResult, Object JavaDoc tableProperties)
80     {
81         /* correlationName is always null */
82         super.init(null, tableProperties);
83         this.childResult = (ResultSetNode) childResult;
84
85         /* Propagate the child's referenced table map, if one exists */
86         if (this.childResult.getReferencedTableMap() != null)
87         {
88             referencedTableMap =
89                 (JBitSet) this.childResult.getReferencedTableMap().clone();
90         }
91     }
92
93     /** @see Optimizable#getTrulyTheBestAccessPath */
94     public AccessPath getTrulyTheBestAccessPath()
95     {
96         if (hasTrulyTheBestAccessPath)
97         {
98             return super.getTrulyTheBestAccessPath();
99         }
100
101         if (childResult instanceof Optimizable)
102             return ((Optimizable) childResult).getTrulyTheBestAccessPath();
103
104         return super.getTrulyTheBestAccessPath();
105     }
106
107     /**
108      * Return the childResult from this node.
109      *
110      * @return ResultSetNode The childResult from this node.
111      */

112     public ResultSetNode getChildResult()
113     {
114         return childResult;
115     }
116
117     /**
118      * Set the childResult for this node.
119      *
120      * @param childResult The new childResult for this node.
121      */

122     void setChildResult(ResultSetNode childResult)
123     {
124         this.childResult = childResult;
125     }
126
127     /**
128      * @see Optimizable#pullOptPredicates
129      *
130      * @exception StandardException Thrown on error
131      */

132     public void pullOptPredicates(
133                                 OptimizablePredicateList optimizablePredicates)
134             throws StandardException
135     {
136         if (childResult instanceof Optimizable)
137         {
138             ((Optimizable) childResult).pullOptPredicates(optimizablePredicates);
139         }
140     }
141
142     /** @see Optimizable#forUpdate */
143     public boolean forUpdate()
144     {
145         if (childResult instanceof Optimizable)
146         {
147             return ((Optimizable) childResult).forUpdate();
148         }
149         else
150         {
151             return super.forUpdate();
152         }
153     }
154
155     /**
156      * @see Optimizable#initAccessPaths
157      */

158     public void initAccessPaths(Optimizer optimizer)
159     {
160         super.initAccessPaths(optimizer);
161         if (childResult instanceof Optimizable)
162         {
163             ((Optimizable) childResult).initAccessPaths(optimizer);
164         }
165     }
166
167     /**
168      * @see Optimizable#updateBestPlanMap
169      *
170      * Makes a call to add/load/remove a plan mapping for this node,
171      * and then makes the necessary call to recurse on this node's
172      * child, in order to ensure that we've handled the full plan
173      * all the way down this node's subtree.
174      */

175     public void updateBestPlanMap(short action,
176         Object JavaDoc planKey) throws StandardException
177     {
178         super.updateBestPlanMap(action, planKey);
179
180         // Now walk the child. Note that if the child is not an
181
// Optimizable and the call to child.getOptimizerImpl()
182
// returns null, then that means we haven't tried to optimize
183
// the child yet. So in that case there's nothing to
184
// add/load.
185

186         if (childResult instanceof Optimizable)
187         {
188             ((Optimizable)childResult).
189                 updateBestPlanMap(action, planKey);
190         }
191         else if (childResult.getOptimizerImpl() != null)
192         {
193             childResult.getOptimizerImpl().
194                 updateBestPlanMaps(action, planKey);
195         }
196     }
197
198     /**
199      * Prints the sub-nodes of this object. See QueryTreeNode.java for
200      * how tree printing is supposed to work.
201      *
202      * @param depth The depth of this node in the tree
203      */

204
205     public void printSubNodes(int depth)
206     {
207         if (SanityManager.DEBUG)
208         {
209             super.printSubNodes(depth);
210
211             if (childResult != null)
212             {
213                 printLabel(depth, "childResult: ");
214                 childResult.treePrint(depth + 1);
215             }
216         }
217     }
218
219     /**
220      * Search to see if a query references the specifed table name.
221      *
222      * @param name Table name (String) to search for.
223      * @param baseTable Whether or not name is for a base table
224      *
225      * @return true if found, else false
226      *
227      * @exception StandardException Thrown on error
228      */

229     public boolean referencesTarget(String JavaDoc name, boolean baseTable)
230         throws StandardException
231     {
232         return childResult.referencesTarget(name, baseTable);
233     }
234
235     /**
236      * Return true if the node references SESSION schema tables (temporary or permanent)
237      *
238      * @return true if references SESSION schema tables, else false
239      *
240      * @exception StandardException Thrown on error
241      */

242     public boolean referencesSessionSchema()
243         throws StandardException
244     {
245         return childResult.referencesSessionSchema();
246     }
247
248     /**
249      * Set the (query block) level (0-based) for this FromTable.
250      *
251      * @param level The query block level for this FromTable.
252      */

253     public void setLevel(int level)
254     {
255         super.setLevel(level);
256         if (childResult instanceof FromTable)
257         {
258             ((FromTable) childResult).setLevel(level);
259         }
260     }
261
262     /**
263      * Return whether or not this ResultSetNode contains a subquery with a
264      * reference to the specified target.
265      *
266      * @param name The table name.
267      * @param baseTable Whether or not the name is for a base table.
268      *
269      * @return boolean Whether or not a reference to the table was found.
270      *
271      * @exception StandardException Thrown on error
272      */

273     boolean subqueryReferencesTarget(String JavaDoc name, boolean baseTable)
274         throws StandardException
275     {
276         return childResult.subqueryReferencesTarget(name, baseTable);
277     }
278
279     /**
280      * Put a ProjectRestrictNode on top of each FromTable in the FromList.
281      * ColumnReferences must continue to point to the same ResultColumn, so
282      * that ResultColumn must percolate up to the new PRN. However,
283      * that ResultColumn will point to a new expression, a VirtualColumnNode,
284      * which points to the FromTable and the ResultColumn that is the source for
285      * the ColumnReference.
286      * (The new PRN will have the original of the ResultColumnList and
287      * the ResultColumns from that list. The FromTable will get shallow copies
288      * of the ResultColumnList and its ResultColumns. ResultColumn.expression
289      * will remain at the FromTable, with the PRN getting a new
290      * VirtualColumnNode for each ResultColumn.expression.)
291      * We then project out the non-referenced columns. If there are no referenced
292      * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
293      * whose expression is 1.
294      *
295      * @param numTables Number of tables in the DML Statement
296      * @param gbl The group by list, if any
297      * @param fromList The from list, if any
298      *
299      * @return The generated ProjectRestrictNode atop the original FromTable.
300      *
301      * @exception StandardException Thrown on error
302      */

303
304     public ResultSetNode preprocess(int numTables,
305                                     GroupByList gbl,
306                                     FromList fromList)
307                                 throws StandardException
308     {
309         childResult = childResult.preprocess(numTables, gbl, fromList);
310
311         /* Build the referenced table map */
312         referencedTableMap = (JBitSet) childResult.getReferencedTableMap().clone();
313
314         return this;
315     }
316
317     /**
318      * Add a new predicate to the list. This is useful when doing subquery
319      * transformations, when we build a new predicate with the left side of
320      * the subquery operator and the subquery's result column.
321      *
322      * @param predicate The predicate to add
323      *
324      * @return ResultSetNode The new top of the tree.
325      *
326      * @exception StandardException Thrown on error
327      */

328     public ResultSetNode addNewPredicate(Predicate predicate)
329             throws StandardException
330     {
331         childResult = childResult.addNewPredicate(predicate);
332         return this;
333     }
334
335     /**
336      * Push expressions down to the first ResultSetNode which can do expression
337      * evaluation and has the same referenced table map.
338      * RESOLVE - This means only pushing down single table expressions to
339      * DistinctNodes today. Once we have a better understanding of how
340      * the optimizer will work, we can push down join clauses.
341      *
342      * @param predicateList The PredicateList.
343      *
344      * @exception StandardException Thrown on error
345      */

346     public void pushExpressions(PredicateList predicateList)
347                     throws StandardException
348     {
349         if (childResult instanceof FromTable)
350         {
351             ((FromTable) childResult).pushExpressions(predicateList);
352         }
353     }
354
355     /**
356      * Evaluate whether or not the subquery in a FromSubquery is flattenable.
357      * Currently, a FSqry is flattenable if all of the following are true:
358      * o Subquery is a SelectNode.
359      * o It contains no top level subqueries. (RESOLVE - we can relax this)
360      * o It does not contain a group by or having clause
361      * o It does not contain aggregates.
362      *
363      * @param fromList The outer from list
364      *
365      * @return boolean Whether or not the FromSubquery is flattenable.
366      */

367     public boolean flattenableInFromSubquery(FromList fromList)
368     {
369         /* Flattening currently involves merging predicates and FromLists.
370          * We don't have a FromList, so we can't flatten for now.
371          */

372         /* RESOLVE - this will introduce yet another unnecessary PRN */
373         return false;
374     }
375
376     /**
377      * Ensure that the top of the RSN tree has a PredicateList.
378      *
379      * @param numTables The number of tables in the query.
380      * @return ResultSetNode A RSN tree with a node which has a PredicateList on top.
381      *
382      * @exception StandardException Thrown on error
383      */

384     public ResultSetNode ensurePredicateList(int numTables)
385         throws StandardException
386     {
387         return this;
388     }
389
390     /**
391      * Optimize this SingleChildResultSetNode.
392      *
393      * @param dataDictionary The DataDictionary to use for optimization
394      * @param predicates The PredicateList to optimize. This should
395      * be a join predicate.
396      * @param outerRows The number of outer joining rows
397      *
398      * @return ResultSetNode The top of the optimized subtree
399      *
400      * @exception StandardException Thrown on error
401      */

402
403     public ResultSetNode optimize(DataDictionary dataDictionary,
404                                   PredicateList predicates,
405                                   double outerRows)
406                     throws StandardException
407     {
408         /* We need to implement this method since a NRSN can appear above a
409          * SelectNode in a query tree.
410          */

411         childResult = childResult.optimize(
412                                         dataDictionary,
413                                         predicates,
414                                         outerRows);
415
416         Optimizer optimizer =
417                             getOptimizer(
418                                 (FromList) getNodeFactory().getNode(
419                                     C_NodeTypes.FROM_LIST,
420                                     getNodeFactory().doJoinOrderOptimization(),
421                                     getContextManager()),
422                             predicates,
423                             dataDictionary,
424                             (RequiredRowOrdering) null);
425         costEstimate = optimizer.newCostEstimate();
426         costEstimate.setCost(childResult.getCostEstimate().getEstimatedCost(),
427                             childResult.getCostEstimate().rowCount(),
428                             childResult.getCostEstimate().singleScanRowCount());
429
430         return this;
431     }
432
433     /**
434      * @see ResultSetNode#modifyAccessPaths
435      *
436      * @exception StandardException Thrown on error
437      */

438     public ResultSetNode modifyAccessPaths() throws StandardException
439     {
440         childResult = childResult.modifyAccessPaths();
441
442         return this;
443     }
444
445     /**
446      * @see ResultSetNode#changeAccessPath
447      *
448      * @exception StandardException Thrown on error
449      */

450     public ResultSetNode changeAccessPath() throws StandardException
451     {
452         childResult = childResult.changeAccessPath();
453         return this;
454     }
455
456     /**
457      * Determine whether or not the specified name is an exposed name in
458      * the current query block.
459      *
460      * @param name The specified name to search for as an exposed name.
461      * @param schemaName Schema name, if non-null.
462      * @param exactMatch Whether or not we need an exact match on specified schema and table
463      * names or match on table id.
464      *
465      * @return The FromTable, if any, with the exposed name.
466      *
467      * @exception StandardException Thrown on error
468      */

469     protected FromTable getFromTableByName(String JavaDoc name, String JavaDoc schemaName, boolean exactMatch)
470         throws StandardException
471     {
472         return childResult.getFromTableByName(name, schemaName, exactMatch);
473     }
474
475     /**
476      * Decrement (query block) level (0-based) for this FromTable.
477      * This is useful when flattening a subquery.
478      *
479      * @param decrement The amount to decrement by.
480      */

481     void decrementLevel(int decrement)
482     {
483         super.decrementLevel(decrement);
484         childResult.decrementLevel(decrement);
485     }
486
487     /**
488      * Get the lock mode for the target of an update statement
489      * (a delete or update). The update mode will always be row for
490      * CurrentOfNodes. It will be table if there is no where clause.
491      *
492      * @return The lock mode
493      */

494     public int updateTargetLockMode()
495     {
496         return childResult.updateTargetLockMode();
497     }
498
499     /**
500      * Return whether or not the underlying ResultSet tree
501      * is ordered on the specified columns.
502      * RESOLVE - This method currently only considers the outermost table
503      * of the query block.
504      *
505      * @param crs The specified ColumnReference[]
506      * @param permuteOrdering Whether or not the order of the CRs in the array can be permuted
507      * @param fbtVector Vector that is to be filled with the FromBaseTable
508      *
509      * @return Whether the underlying ResultSet tree
510      * is ordered on the specified column.
511      *
512      * @exception StandardException Thrown on error
513      */

514     boolean isOrderedOn(ColumnReference[] crs, boolean permuteOrdering, Vector JavaDoc fbtVector)
515                 throws StandardException
516     {
517         return childResult.isOrderedOn(crs, permuteOrdering, fbtVector);
518     }
519
520     /**
521      * Return whether or not the underlying ResultSet tree will return
522      * a single row, at most.
523      * This is important for join nodes where we can save the extra next
524      * on the right side if we know that it will return at most 1 row.
525      *
526      * @return Whether or not the underlying ResultSet tree will return a single row.
527      * @exception StandardException Thrown on error
528      */

529     public boolean isOneRowResultSet() throws StandardException
530     {
531         // Default is false
532
return childResult.isOneRowResultSet();
533     }
534
535     /**
536      * Return whether or not the underlying ResultSet tree is for a NOT EXISTS join.
537      *
538      * @return Whether or not the underlying ResultSet tree is for a NOT EXISTS.
539      */

540     public boolean isNotExists()
541     {
542         return childResult.isNotExists();
543     }
544
545     /**
546      * Determine whether we need to do reflection in order to do the projection.
547      * Reflection is only needed if there is at least 1 column which is not
548      * simply selecting the source column.
549      *
550      * @return Whether or not we need to do reflection in order to do
551      * the projection.
552      */

553     protected boolean reflectionNeededForProjection()
554     {
555         return ! (resultColumns.allExpressionsAreColumns(childResult));
556     }
557
558     /**
559      * Replace any DEFAULTs with the associated tree for the default.
560      *
561      * @param ttd The TableDescriptor for the target table.
562      * @param tcl The RCL for the target table.
563      *
564      * @exception StandardException Thrown on error
565      */

566     void replaceDefaults(TableDescriptor ttd, ResultColumnList tcl)
567         throws StandardException
568     {
569         childResult.replaceDefaults(ttd, tcl);
570     }
571
572     /**
573      * Notify the underlying result set tree that the result is
574      * ordering dependent. (For example, no bulk fetch on an index
575      * if under an IndexRowToBaseRow.)
576      */

577     void markOrderingDependent()
578     {
579         childResult.markOrderingDependent();
580     }
581
582     /**
583      * Get the final CostEstimate for this node.
584      *
585      * @return The final CostEstimate for this node, which is
586      * the final cost estimate for the child node.
587      */

588     public CostEstimate getFinalCostEstimate()
589         throws StandardException
590     {
591         /*
592         ** The cost estimate will be set here if either optimize() or
593         ** optimizeIt() was called on this node. It's also possible
594         ** that optimization was done directly on the child node,
595         ** in which case the cost estimate will be null here.
596         */

597         if (costEstimate == null)
598             return childResult.getFinalCostEstimate();
599         else
600         {
601             return costEstimate;
602         }
603     }
604
605     /**
606      * Accept a visitor, and call v.visit()
607      * on child nodes as necessary.
608      *
609      * @param v the visitor
610      *
611      * @exception StandardException on error
612      */

613     public Visitable accept(Visitor v)
614         throws StandardException
615     {
616         if (v.skipChildren(this))
617         {
618             return v.visit(this);
619         }
620
621         Visitable returnNode = super.accept(v);
622
623         if (childResult != null && !v.stopTraversal())
624         {
625             childResult = (ResultSetNode)childResult.accept(v);
626         }
627
628         return returnNode;
629     }
630 }
631
Popular Tags