KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.FromSubquery
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.reference.SQLState;
25
26 import org.apache.derby.iapi.services.context.ContextManager;
27
28 import org.apache.derby.iapi.error.StandardException;
29 import org.apache.derby.iapi.sql.compile.CompilerContext;
30 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
31 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
32
33 import org.apache.derby.iapi.services.sanity.SanityManager;
34
35 import org.apache.derby.iapi.util.JBitSet;
36
37 import java.util.Properties JavaDoc;
38
39 /**
40  * A FromSubquery represents a subquery in the FROM list of a DML statement.
41  *
42  * The current implementation of this class is only
43  * sufficient for Insert's need to push a new
44  * select on top of the one the user specified,
45  * to make the selected structure match that
46  * of the insert target table.
47  *
48  * @author Jeff Lichtman
49  */

50 public class FromSubquery extends FromTable
51 {
52     boolean generatedForGroupByClause;
53     boolean generatedForHavingClause;
54     ResultSetNode subquery;
55
56     /**
57      * Intializer for a table in a FROM list.
58      *
59      * @param subquery The subquery
60      * @param correlationName The correlation name
61      * @param derivedRCL The derived column list
62      * @param tableProperties Properties list associated with the table
63      */

64     public void init(
65                     Object JavaDoc subquery,
66                     Object JavaDoc correlationName,
67                     Object JavaDoc derivedRCL,
68                     Object JavaDoc tableProperties)
69     {
70         super.init(correlationName, tableProperties);
71         this.subquery = (ResultSetNode) subquery;
72         resultColumns = (ResultColumnList) derivedRCL;
73     }
74
75     /**
76      * Convert this object to a String. See comments in QueryTreeNode.java
77      * for how this should be done for tree printing.
78      *
79      * @return This object as a String
80      */

81
82     public String JavaDoc toString()
83     {
84         if (SanityManager.DEBUG)
85         {
86             return
87               "generatedForGroupByClause: " + generatedForGroupByClause + "\n" +
88               "generatedForHavingClause: " + generatedForHavingClause + "\n" +
89               super.toString();
90         }
91         else
92         {
93             return "";
94         }
95     }
96
97     /**
98      * Prints the sub-nodes of this object. See QueryTreeNode.java for
99      * how tree printing is supposed to work.
100      *
101      * @param depth The depth of this node in the tree
102      */

103
104     public void printSubNodes(int depth)
105     {
106         if (SanityManager.DEBUG) {
107             super.printSubNodes(depth);
108
109             if (subquery != null)
110             {
111                 printLabel(depth, "subquery: ");
112                 subquery.treePrint(depth + 1);
113             }
114         }
115     }
116
117     /**
118      * Return the "subquery" from this node.
119      *
120      * @return ResultSetNode The "subquery" from this node.
121      */

122     public ResultSetNode getSubquery()
123     {
124         return subquery;
125     }
126
127     /**
128      * Mark this FromSubquery as being generated for a GROUP BY clause.
129      * (This node represents the SELECT thru GROUP BY clauses. We
130      * appear in the FromList of a SelectNode generated to represent
131      * the result of the GROUP BY. This allows us to add ResultColumns
132      * to the SelectNode for the user's query.
133      */

134     public void markAsForGroupByClause()
135     {
136         generatedForGroupByClause = true;
137     }
138
139     /**
140      * Mark this FromSubquery as being generated for a HAVING clause.
141      * (This node represents the SELECT thru GROUP BY clauses. We
142      * appear in the FromList of a SelectNode generated to represent
143      * the actual HAVING clause.
144      */

145     public void markAsForHavingClause()
146     {
147         generatedForHavingClause = true;
148     }
149
150     /**
151      * Determine whether or not the specified name is an exposed name in
152      * the current query block.
153      *
154      * @param name The specified name to search for as an exposed name.
155      * @param schemaName Schema name, if non-null.
156      * @param exactMatch Whether or not we need an exact match on specified schema and table
157      * names or match on table id.
158      *
159      * @return The FromTable, if any, with the exposed name.
160      *
161      * @exception StandardException Thrown on error
162      */

163     protected FromTable getFromTableByName(String JavaDoc name, String JavaDoc schemaName, boolean exactMatch)
164         throws StandardException
165     {
166         if (generatedForGroupByClause || generatedForHavingClause)
167         {
168             return subquery.getFromTableByName(name, schemaName, exactMatch);
169         }
170         else
171         {
172             return super.getFromTableByName(name, schemaName, exactMatch);
173         }
174     }
175
176     /**
177      * Bind this subquery that appears in the FROM list.
178      *
179      * @param dataDictionary The DataDictionary to use for binding
180      * @param fromListParam FromList to use/append to.
181      *
182      * @return ResultSetNode The bound FromSubquery.
183      *
184      * @exception StandardException Thrown on error
185      */

186
187     public ResultSetNode bindNonVTITables(DataDictionary dataDictionary,
188                           FromList fromListParam)
189                             throws StandardException
190     {
191         /* Assign the tableNumber */
192         if (tableNumber == -1) // allow re-bind, in which case use old number
193
tableNumber = getCompilerContext().getNextTableNumber();
194
195         subquery = subquery.bindNonVTITables(dataDictionary, fromListParam);
196
197         return this;
198     }
199
200     /**
201      * Bind this subquery that appears in the FROM list.
202      *
203      * @param fromListParam FromList to use/append to.
204      *
205      * @return ResultSetNode The bound FromSubquery.
206      *
207      * @exception StandardException Thrown on error
208      */

209
210     public ResultSetNode bindVTITables(FromList fromListParam)
211                             throws StandardException
212     {
213         subquery = subquery.bindVTITables(fromListParam);
214
215         return this;
216     }
217
218     /**
219      * Check for (and reject) ? parameters directly under the ResultColumns.
220      * This is done for SELECT statements. For FromSubquery, we
221      * simply pass the check through to the subquery.
222      *
223      * @exception StandardException Thrown if a ? parameter found
224      * directly under a ResultColumn
225      */

226
227     public void rejectParameters() throws StandardException
228     {
229         subquery.rejectParameters();
230     }
231
232     /**
233      * Bind the expressions in this FromSubquery. This means
234      * binding the sub-expressions, as well as figuring out what the return
235      * type is for each expression.
236      *
237      * @exception StandardException Thrown on error
238      */

239
240     public void bindExpressions(FromList fromListParam)
241                     throws StandardException
242     {
243         FromList emptyFromList =
244                                 (FromList) getNodeFactory().getNode(
245                                     C_NodeTypes.FROM_LIST,
246                                     getNodeFactory().doJoinOrderOptimization(),
247                                     getContextManager());
248         ResultColumnList derivedRCL = resultColumns;
249         ResultColumnList subqueryRCL;
250         FromList nestedFromList;
251
252         /* From subqueries cannot be correlated, so we pass an empty FromList
253          * to subquery.bindExpressions() and .bindResultColumns(). However,
254          * the parser rewrites queries which have GROUP BY and HAVING clauses.
255          * For these rewritten pseudo-subqueries, we need to pass in the outer FromList
256          * which contains correlated tables.
257          */

258         if ( generatedForGroupByClause || generatedForHavingClause )
259         { nestedFromList = fromListParam; }
260         else { nestedFromList = emptyFromList; }
261         
262         subquery.bindExpressions(nestedFromList);
263         subquery.bindResultColumns(nestedFromList);
264
265         /* Now that we've bound the expressions in the subquery, we
266          * can propagate the subquery's RCL up to the FromSubquery.
267          * Get the subquery's RCL, assign shallow copy back to
268          * it and create new VirtualColumnNodes for the original's
269          * ResultColumn.expressions.
270          * NOTE: If the size of the derived column list is less than
271          * the size of the subquery's RCL and the derived column list is marked
272          * for allowing a size mismatch, then we have a select * view
273          * on top of a table that has had columns added to it via alter table.
274          * In this case, we trim out the columns that have been added to
275          * the table since the view was created.
276          */

277         subqueryRCL = subquery.getResultColumns();
278         if (resultColumns != null && resultColumns.getCountMismatchAllowed() &&
279             resultColumns.size() < subqueryRCL.size())
280         {
281             for (int index = subqueryRCL.size() - 1;
282                  index >= resultColumns.size();
283                  index--)
284             {
285                 subqueryRCL.removeElementAt(index);
286             }
287         }
288
289         subquery.setResultColumns(subqueryRCL.copyListAndObjects());
290         subqueryRCL.genVirtualColumnNodes(subquery, subquery.getResultColumns());
291         resultColumns = subqueryRCL;
292
293         /* Propagate the name info from the derived column list */
294         if (derivedRCL != null)
295         {
296              resultColumns.propagateDCLInfo(derivedRCL, correlationName);
297         }
298     }
299
300     /**
301      * Try to find a ResultColumn in the table represented by this FromBaseTable
302      * that matches the name in the given ColumnReference.
303      *
304      * @param columnReference The columnReference whose name we're looking
305      * for in the given table.
306      *
307      * @return A ResultColumn whose expression is the ColumnNode
308      * that matches the ColumnReference.
309      * Returns null if there is no match.
310      *
311      * @exception StandardException Thrown on error
312      */

313
314     public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException
315     {
316         ResultColumn resultColumn = null;
317         String JavaDoc columnsTableName;
318
319         /*
320         ** RESOLVE: When we add support for schemas, check to see if
321         ** the column name specifies a schema, and if so, if this
322         ** table is in that schema.
323         */

324
325         columnsTableName = columnReference.getTableName();
326
327         /* We have 5 cases here:
328          * 1. ColumnReference was generated to replace an aggregate.
329          * (We are the wrapper for a HAVING clause and the ColumnReference
330          * was generated to reference the aggregate which was pushed down into
331          * the SELECT list in the user's query.)
332          * Just do what you would expect. Try to resolve the
333          * ColumnReference against our RCL if the ColumnReference is unqualified
334          * or if it is qualified with our exposed name.
335          * 2. We are the wrapper for a GROUP BY and a HAVING clause and
336          * either the ColumnReference is qualified or it is in
337          * the HAVING clause. For example:
338          * select a from t1 group by a having t1.a = 1
339          * select a as asdf from t1 group by a having a = 1
340          * We need to match against the underlying FromList and then find
341          * the grandparent ResultColumn in our RCL so that we return a
342          * ResultColumn from the correct ResultSetNode. It is okay not to
343          * find a matching grandparent node. In fact, this is how we ensure
344          * the correct semantics for ColumnReferences in the HAVING clause
345          * (which must be bound against the GROUP BY list.)
346          * 3. We are the wrapper for a HAVING clause without a GROUP BY and
347          * the ColumnReference is from the HAVING clause. ColumnReferences
348          * are invalid in this case, so we return null.
349          * 4. We are the wrapper for a GROUP BY with no HAVING. This has
350          * to be a separate case because of #5 and the following query:
351          * select * from (select c1 from t1) t, (select c1 from t1) tt
352          * group by t1.c1, tt.c1
353          * (The correlation names are lost in the generated FromSuquery.)
354          * 5. Everything else - do what you would expect. Try to resolve the
355          * ColumnReference against our RCL if the ColumnReference is unqualified
356          * or if it is qualified with our exposed name.
357          */

358         if (columnReference.getGeneratedToReplaceAggregate()) // 1
359
{
360             resultColumn = resultColumns.getResultColumn(columnReference.getColumnName());
361         }
362         else if (generatedForGroupByClause && generatedForHavingClause &&
363                  (columnsTableName != null ||
364                   columnReference.getClause() != ValueNode.IN_SELECT_LIST)) // 2
365
{
366             if (SanityManager.DEBUG)
367             {
368                 SanityManager.ASSERT(correlationName == null,
369                     "correlationName expected to be null");
370                 SanityManager.ASSERT(subquery instanceof SelectNode,
371                     "subquery expected to be instanceof SelectNode, not " +
372                     subquery.getClass().getName());
373             }
374
375             SelectNode select = (SelectNode) subquery;
376
377             resultColumn = select.getFromList().bindColumnReference(columnReference);
378
379             /* Find and return the matching RC from our RCL.
380              * (Not an error if no match found. Let ColumnReference deal with it.
381              */

382             if (resultColumn != null)
383             {
384                 /* Is there a matching resultColumn in the subquery's RCL? */
385                 resultColumn = subquery.getResultColumns().findParentResultColumn(
386                                                 resultColumn);
387                 if (resultColumn != null)
388                 {
389                     /* Is there a matching resultColumn in our RCL? */
390                     resultColumn = resultColumns.findParentResultColumn(
391                                                 resultColumn);
392                 }
393             }
394         }
395         else if ((generatedForHavingClause && ! generatedForGroupByClause) // 3
396
&& (columnReference.getClause() != ValueNode.IN_SELECT_LIST) )
397         {
398             resultColumn = null;
399         }
400         else if (generatedForGroupByClause) // 4
401
{
402                 resultColumn = resultColumns.getResultColumn(
403                                      columnsTableName,
404                                      columnReference.getColumnName());
405         }
406         else if (columnsTableName == null || columnsTableName.equals(correlationName)) // 5?
407
{
408             resultColumn = resultColumns.getAtMostOneResultColumn(columnReference, correlationName);
409         }
410             
411
412         if (resultColumn != null)
413         {
414             columnReference.setTableNumber(tableNumber);
415         }
416
417         return resultColumn;
418     }
419
420     /**
421      * Preprocess a ResultSetNode - this currently means:
422      * o Generating a referenced table map for each ResultSetNode.
423      * o Putting the WHERE and HAVING clauses in conjunctive normal form (CNF).
424      * o Converting the WHERE and HAVING clauses into PredicateLists and
425      * classifying them.
426      * o Ensuring that a ProjectRestrictNode is generated on top of every
427      * FromBaseTable and generated in place of every FromSubquery.
428      * o Pushing single table predicates down to the new ProjectRestrictNodes.
429      *
430      * @param numTables The number of tables in the DML Statement
431      * @param gbl The group by list, if any
432      * @param fromList The from list, if any
433      *
434      * @return ResultSetNode at top of preprocessed tree.
435      *
436      * @exception StandardException Thrown on error
437      */

438
439     public ResultSetNode preprocess(int numTables,
440                                     GroupByList gbl,
441                                     FromList fromList)
442                                 throws StandardException
443     {
444         /* We want to chop out the FromSubquery from the tree and replace it
445          * with a ProjectRestrictNode. One complication is that there may be
446          * ColumnReferences above us which point to the FromSubquery's RCL.
447          * What we want to return is a tree with a PRN with the
448          * FromSubquery's RCL on top. (In addition, we don't want to be
449          * introducing any redundant ProjectRestrictNodes.)
450          * Another complication is that we want to be able to only only push
451          * projections and restrictions down to this ProjectRestrict, but
452          * we want to be able to push them through as well.
453          * So, we:
454          * o call subquery.preprocess() which returns a tree with
455          * a SelectNode or a RowResultSetNode on top.
456          * o If the FSqry is flattenable(), then we return (so that the
457          * caller can then call flatten()), otherwise we:
458          * o generate a PRN, whose RCL is the FSqry's RCL, on top of the result.
459          * o create a referencedTableMap for the PRN which represents
460          * the FSqry's tableNumber, since ColumnReferences in the outer
461          * query block would be referring to that one.
462          * (This will allow us to push restrictions down to the PRN.)
463          */

464
465         subquery = subquery.preprocess(numTables, gbl, fromList);
466
467         /* Return if the FSqry is flattenable()
468          * NOTE: We can't flatten a FromSubquery if there is a group by list
469          * because the group by list must be ColumnReferences. For:
470          * select c1 from v1 group by c1,
471          * where v1 is select 1 from t1
472          * The expression under the last redundant ResultColumn is an IntConstantNode,
473          * not a ColumnReference.
474          * We also do not flatten a subquery if tableProperties is non-null,
475          * as the user is specifying 1 or more properties for the derived table,
476          * which could potentially be lost on the flattening.
477          * RESOLVE - this is too restrictive.
478          */

479         if ((gbl == null || gbl.size() == 0) &&
480             tableProperties == null &&
481             subquery.flattenableInFromSubquery(fromList))
482         {
483             /* Set our table map to the subquery's table map. */
484             setReferencedTableMap(subquery.getReferencedTableMap());
485             return this;
486         }
487
488         return extractSubquery(numTables);
489     }
490
491     /**
492      * Extract out and return the subquery, with a PRN on top.
493      * (See FromSubquery.preprocess() for more details.)
494      *
495      * @param numTables The number of tables in the DML Statement
496      *
497      * @return ResultSetNode at top of extracted tree.
498      *
499      * @exception StandardException Thrown on error
500      */

501
502     public ResultSetNode extractSubquery(int numTables)
503         throws StandardException
504     {
505         JBitSet newJBS;
506         ResultSetNode newPRN;
507
508         newPRN = (ResultSetNode) getNodeFactory().getNode(
509                                 C_NodeTypes.PROJECT_RESTRICT_NODE,
510                                 subquery, /* Child ResultSet */
511                                 resultColumns, /* Projection */
512                                 null, /* Restriction */
513                                 null, /* Restriction as PredicateList */
514                                 null, /* Subquerys in Projection */
515                                 null, /* Subquerys in Restriction */
516                                 tableProperties,
517                                 getContextManager() );
518
519         /* Set up the PRN's referencedTableMap */
520         newJBS = new JBitSet(numTables);
521         newJBS.set(tableNumber);
522         newPRN.setReferencedTableMap(newJBS);
523         ((FromTable) newPRN).setTableNumber(tableNumber);
524
525         return newPRN;
526     }
527
528     /**
529      * Flatten this FSqry into the outer query block. The steps in
530      * flattening are:
531      * o Mark all ResultColumns as redundant, so that they are "skipped over"
532      * at generate().
533      * o Append the wherePredicates to the outer list.
534      * o Return the fromList so that the caller will merge the 2 lists
535      * RESOLVE - FSqrys with subqueries are currently not flattenable. Some of
536      * them can be flattened, however. We need to merge the subquery list when
537      * we relax this restriction.
538      *
539      * NOTE: This method returns NULL when flattening RowResultSetNodes
540      * (the node for a VALUES clause). The reason is that no reference
541      * is left to the RowResultSetNode after flattening is done - the
542      * expressions point directly to the ValueNodes in the RowResultSetNode's
543      * ResultColumnList.
544      *
545      * @param rcl The RCL from the outer query
546      * @param outerPList PredicateList to append wherePredicates to.
547      * @param sql The SubqueryList from the outer query
548      * @param gbl The group by list, if any
549      *
550      * @return FromList The fromList from the underlying SelectNode.
551      *
552      * @exception StandardException Thrown on error
553      */

554     public FromList flatten(ResultColumnList rcl,
555                             PredicateList outerPList,
556                             SubqueryList sql,
557                             GroupByList gbl)
558
559             throws StandardException
560     {
561         FromList fromList = null;
562         SelectNode selectNode;
563
564         resultColumns.setRedundant();
565
566         subquery.getResultColumns().setRedundant();
567
568         /*
569         ** RESOLVE: Each type of result set should know how to remap itself.
570         */

571         if (subquery instanceof SelectNode)
572         {
573             selectNode = (SelectNode) subquery;
574             fromList = selectNode.getFromList();
575
576             // selectNode.getResultColumns().setRedundant();
577

578             if (selectNode.getWherePredicates().size() > 0)
579             {
580                 outerPList.destructiveAppend(selectNode.getWherePredicates());
581             }
582
583             if (selectNode.getWhereSubquerys().size() > 0)
584             {
585                 sql.destructiveAppend(selectNode.getWhereSubquerys());
586             }
587         }
588         else if ( ! (subquery instanceof RowResultSetNode))
589         {
590             if (SanityManager.DEBUG)
591             {
592                 SanityManager.THROWASSERT("subquery expected to be either a SelectNode or a RowResultSetNode, but is a " + subquery.getClass().getName());
593             }
594         }
595
596         /* Remap all ColumnReferences from the outer query to this node.
597          * (We replace those ColumnReferences with clones of the matching
598          * expression in the SELECT's RCL.
599          */

600         rcl.remapColumnReferencesToExpressions();
601         outerPList.remapColumnReferencesToExpressions();
602         if (gbl != null)
603         {
604             gbl.remapColumnReferencesToExpressions();
605         }
606
607         return fromList;
608     }
609
610     /**
611      * Get the exposed name for this table, which is the name that can
612      * be used to refer to it in the rest of the query.
613      *
614      * @return The exposed name for this table.
615      */

616
617     public String JavaDoc getExposedName()
618     {
619         return correlationName;
620     }
621
622     /**
623      * Expand a "*" into a ResultColumnList with all of the
624      * result columns from the subquery.
625      * @exception StandardException Thrown on error
626      */

627     public ResultColumnList getAllResultColumns(TableName allTableName)
628             throws StandardException
629     {
630         ResultColumnList rcList = null;
631         TableName exposedName;
632         TableName toCompare;
633
634
635         if(allTableName != null)
636              toCompare = makeTableName(allTableName.getSchemaName(),correlationName);
637         else
638             toCompare = makeTableName(null,correlationName);
639         
640         if ( allTableName != null &&
641              ! allTableName.equals(toCompare))
642         {
643             return null;
644         }
645
646         /* Cache exposed name for this table.
647          * The exposed name becomes the qualifier for each column
648          * in the expanded list.
649          */

650         exposedName = makeTableName(null, correlationName);
651
652         rcList = (ResultColumnList) getNodeFactory().getNode(
653                                         C_NodeTypes.RESULT_COLUMN_LIST,
654                                         getContextManager());
655
656         /* Build a new result column list based off of resultColumns.
657          * NOTE: This method will capture any column renaming due to
658          * a derived column list.
659          */

660         int rclSize = resultColumns.size();
661         for (int index = 0; index < rclSize; index++)
662         {
663             ResultColumn resultColumn = (ResultColumn) resultColumns.elementAt(index);
664             ValueNode valueNode;
665             String JavaDoc columnName;
666
667             if (resultColumn.isGenerated())
668             {
669                 continue;
670             }
671
672             // Build a ResultColumn/ColumnReference pair for the column //
673
columnName = resultColumn.getName();
674             boolean isNameGenerated = resultColumn.isNameGenerated();
675
676             /* If this node was generated for a GROUP BY, then tablename for the CR, if any,
677              * comes from the source RC.
678              */

679             TableName tableName;
680
681             if (correlationName == null && generatedForGroupByClause)
682             {
683                 tableName = makeTableName(null, resultColumn.getTableName());
684             }
685             else
686             {
687                 tableName = exposedName;
688             }
689             valueNode = (ValueNode) getNodeFactory().getNode(
690                                             C_NodeTypes.COLUMN_REFERENCE,
691                                             columnName,
692                                             tableName,
693                                             getContextManager());
694             resultColumn = (ResultColumn) getNodeFactory().getNode(
695                                             C_NodeTypes.RESULT_COLUMN,
696                                             columnName,
697                                             valueNode,
698                                             getContextManager());
699
700             resultColumn.setNameGenerated(isNameGenerated);
701             // Build the ResultColumnList to return //
702
rcList.addResultColumn(resultColumn);
703         }
704         return rcList;
705     }
706
707     /**
708      * @see QueryTreeNode#disablePrivilegeCollection
709      */

710     public void disablePrivilegeCollection()
711     {
712         super.disablePrivilegeCollection();
713         subquery.disablePrivilegeCollection();
714     }
715
716     /**
717      * Search to see if a query references the specifed table name.
718      *
719      * @param name Table name (String) to search for.
720      * @param baseTable Whether or not name is for a base table
721      *
722      * @return true if found, else false
723      *
724      * @exception StandardException Thrown on error
725      */

726     public boolean referencesTarget(String JavaDoc name, boolean baseTable)
727         throws StandardException
728     {
729         return subquery.referencesTarget(name, baseTable);
730     }
731
732     /**
733      * Return true if the node references SESSION schema tables (temporary or permanent)
734      *
735      * @return true if references SESSION schema tables, else false
736      *
737      * @exception StandardException Thrown on error
738      */

739     public boolean referencesSessionSchema()
740         throws StandardException
741     {
742         return subquery.referencesSessionSchema();
743     }
744
745     /**
746      * Bind any untyped null nodes to the types in the given ResultColumnList.
747      *
748      * @param bindingRCL The ResultColumnList with the types to bind to.
749      *
750      * @exception StandardException Thrown on error
751      */

752     public void bindUntypedNullsToResultColumns(ResultColumnList bindingRCL)
753                 throws StandardException
754     {
755         subquery.bindUntypedNullsToResultColumns(bindingRCL);
756     }
757
758     /**
759      * Decrement (query block) level (0-based) for this FromTable.
760      * This is useful when flattening a subquery.
761      *
762      * @param decrement The amount to decrement by.
763      */

764     void decrementLevel(int decrement)
765     {
766         super.decrementLevel(decrement);
767         subquery.decrementLevel(decrement);
768     }
769 }
770
Popular Tags