KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ValueNodeList
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.sanity.SanityManager;
25
26 import org.apache.derby.iapi.error.StandardException;
27
28 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
29
30 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
31
32 import org.apache.derby.iapi.types.DataTypeDescriptor;
33 import org.apache.derby.iapi.types.DataValueDescriptor;
34 import org.apache.derby.iapi.types.TypeId;
35
36 import org.apache.derby.iapi.sql.compile.TypeCompiler;
37
38 import org.apache.derby.iapi.reference.SQLState;
39
40 import org.apache.derby.iapi.store.access.Qualifier;
41
42 import org.apache.derby.iapi.util.JBitSet;
43
44 import java.util.Vector JavaDoc;
45
46 /**
47  * A ValueNodeList represents a list of ValueNodes within a specific predicate
48  * (eg, IN list, NOT IN list or BETWEEN) in a DML statement.
49  * It extends QueryTreeNodeVector.
50  *
51  * @author Jerry Brenner
52  */

53
54 public class ValueNodeList extends QueryTreeNodeVector
55 {
56
57     /**
58      * Prints the sub-nodes of this object. See QueryTreeNode.java for
59      * how tree printing is supposed to work.
60      *
61      * @param depth The depth of this node in the tree
62      */

63
64     public void printSubNodes(int depth)
65     {
66         if (SanityManager.DEBUG)
67         {
68             super.printSubNodes(depth);
69
70             for (int index = 0; index < size(); index++)
71             {
72                 ValueNode valueNode;
73                 valueNode = (ValueNode) elementAt(index);
74                 valueNode.treePrint(depth + 1);
75             }
76         }
77     }
78
79     /**
80      * Set the clause that this node appears in.
81      *
82      * @param clause The clause that this node appears in.
83      */

84     public void setClause(int clause)
85     {
86         int size = size();
87
88         for (int index = 0; index < size; index++)
89         {
90             ValueNode valueNode;
91                 valueNode = (ValueNode) elementAt(index);
92             valueNode.setClause(clause);
93         }
94     }
95
96     /**
97      * Add a ValueNode to the list.
98      *
99      * @param valueNode A ValueNode to add to the list
100      *
101      * @exception StandardException Thrown on error
102      */

103
104     public void addValueNode(ValueNode valueNode) throws StandardException
105     {
106         addElement(valueNode);
107     }
108
109     /**
110      * Bind this expression. This means binding the sub-expressions,
111      * as well as figuring out what the return type is for this expression.
112      *
113      * @param fromList The FROM list for the query this
114      * expression is in, for binding columns.
115      * @param subqueryList The subquery list being built as we find SubqueryNodes
116      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
117      *
118      * @exception StandardException Thrown on error
119      */

120     public void bindExpression(FromList fromList,
121                                SubqueryList subqueryList,
122                                Vector JavaDoc aggregateVector)
123             throws StandardException
124     {
125         int size = size();
126
127         for (int index = 0; index < size; index++)
128         {
129             ValueNode vn = (ValueNode) elementAt(index);
130             vn = vn.bindExpression(fromList, subqueryList,
131                                    aggregateVector);
132
133             setElementAt(vn, index);
134         }
135     }
136
137
138     /**
139      * Generate a SQL->Java->SQL conversion tree any node in the list
140      * which is not a system built-in type.
141      * This is useful when doing comparisons, built-in functions, etc. on
142      * java types which have a direct mapping to system built-in types.
143      *
144      * @exception StandardException Thrown on error
145      */

146     public void genSQLJavaSQLTrees()
147         throws StandardException
148     {
149         int size = size();
150
151         for (int index = 0; index < size; index++)
152         {
153             ValueNode valueNode = (ValueNode) elementAt(index);
154             
155             if (valueNode.getTypeId().userType())
156             {
157                 setElementAt(valueNode.genSQLJavaSQLTree(), index);
158             }
159         }
160     }
161
162     /**
163      * Get the dominant DataTypeServices from the elements in the list.
164      *
165      * @return DataTypeServices The dominant DataTypeServices.
166      *
167      * @exception StandardException Thrown on error
168      */

169     public DataTypeDescriptor getDominantTypeServices() throws StandardException
170     {
171         DataTypeDescriptor dominantDTS = null;
172
173         for (int index = 0; index < size(); index++)
174         {
175             ValueNode valueNode;
176
177             valueNode = (ValueNode) elementAt(index);
178             if (valueNode.requiresTypeFromContext())
179                 continue;
180             DataTypeDescriptor valueNodeDTS = valueNode.getTypeServices();
181
182             if (dominantDTS == null)
183             {
184                 dominantDTS = valueNodeDTS;
185             }
186             else
187             {
188                 dominantDTS = dominantDTS.getDominantType(valueNodeDTS, getClassFactory());
189             }
190         }
191
192         return dominantDTS;
193     }
194
195     /**
196      * Get the first non-null DataTypeServices from the elements in the list.
197      *
198      * @return DataTypeServices The first non-null DataTypeServices.
199      *
200      * @exception StandardException Thrown on error
201      */

202     public DataTypeDescriptor getTypeServices() throws StandardException
203     {
204         DataTypeDescriptor firstDTS = null;
205         int size = size();
206
207         for (int index = 0; index < size; index++)
208         {
209             ValueNode valueNode;
210
211             valueNode = (ValueNode) elementAt(index);
212             DataTypeDescriptor valueNodeDTS = valueNode.getTypeServices();
213
214             if ((firstDTS == null) && (valueNodeDTS != null))
215             {
216                 firstDTS = valueNodeDTS;
217                 break;
218             }
219         }
220
221         return firstDTS;
222     }
223
224     /**
225      * Return whether or not all of the entries in the list have the same
226      * type precendence as the specified value.
227      *
228      * @param precedence The specified precedence.
229      *
230      * @return Whether or not all of the entries in the list have the same
231      * type precendence as the specified value.
232      */

233     boolean allSamePrecendence(int precedence)
234     throws StandardException
235     {
236         boolean allSame = true;
237         int size = size();
238
239         for (int index = 0; index < size; index++)
240         {
241             ValueNode valueNode;
242
243             valueNode = (ValueNode) elementAt(index);
244             DataTypeDescriptor valueNodeDTS = valueNode.getTypeServices();
245
246             if (valueNodeDTS == null)
247             {
248                 return false;
249             }
250
251             if (precedence != valueNodeDTS.getTypeId().typePrecedence())
252             {
253                 return false;
254             }
255         }
256
257         return allSame;
258     }
259
260
261     /**
262      * Make sure that passed ValueNode's type is compatible with the non-parameter elements in the ValueNodeList.
263      *
264      * @param leftOperand Check for compatibility against this parameter's type
265      *
266      */

267     public void compatible(ValueNode leftOperand) throws StandardException
268     {
269         int size = size();
270         TypeId leftType;
271         ValueNode valueNode;
272         TypeCompiler leftTC;
273
274         leftType = leftOperand.getTypeId();
275         leftTC = leftOperand.getTypeCompiler();
276
277         for (int index = 0; index < size; index++)
278         {
279             valueNode = (ValueNode) elementAt(index);
280             if (valueNode.requiresTypeFromContext())
281                 continue;
282
283
284             /*
285             ** Are the types compatible to each other? If not, throw an exception.
286             */

287             if (! leftTC.compatible(valueNode.getTypeId()))
288             {
289                 throw StandardException.newException(SQLState.LANG_DB2_COALESCE_DATATYPE_MISMATCH,
290                         leftType.getSQLTypeName(),
291                         valueNode.getTypeId().getSQLTypeName()
292                         );
293             }
294         }
295     }
296
297     /**
298      * Determine whether or not the leftOperand is comparable() with all of
299      * the elements in the list. Throw an exception if any of them are not
300      * comparable.
301      *
302      * @param leftOperand The left side of the expression
303      *
304      * @exception StandardException Thrown on error
305      */

306     public void comparable(ValueNode leftOperand) throws StandardException
307     {
308         int size = size();
309         TypeId leftType;
310         ValueNode valueNode;
311         TypeCompiler leftTC;
312
313         leftType = leftOperand.getTypeId();
314         leftTC = leftOperand.getTypeCompiler();
315
316         for (int index = 0; index < size; index++)
317         {
318             valueNode = (ValueNode) elementAt(index);
319
320             /*
321             ** Can the types be compared to each other? If not, throw an
322             ** exception.
323             */

324             if (! leftTC.comparable(valueNode.getTypeId(),
325                                     false,
326                                     getClassFactory()))
327             {
328                 throw StandardException.newException(SQLState.LANG_NOT_COMPARABLE,
329                         leftType.getSQLTypeName(),
330                         valueNode.getTypeId().getSQLTypeName()
331                         );
332             }
333         }
334     }
335
336     /**
337      * Determine whether or not any of the elements in the list are nullable.
338      *
339      * @return boolean Whether or not any of the elements in the list
340      * are nullable.
341      */

342     public boolean isNullable()
343     throws StandardException
344     {
345         int size = size();
346
347         for (int index = 0; index < size; index++)
348         {
349             if (((ValueNode) elementAt(index)).getTypeServices().isNullable())
350             {
351                 return true;
352             }
353         }
354         return false;
355     }
356                                          
357     /**
358      * Does this list contain a ParameterNode?
359      *
360      * @return boolean Whether or not the list contains a ParameterNode
361      */

362     public boolean containsParameterNode()
363     {
364         int size = size();
365
366         for (int index = 0; index < size; index++)
367         {
368             if (((ValueNode) elementAt(index)).requiresTypeFromContext())
369             {
370                 return true;
371             }
372         }
373         return false;
374     }
375                                          
376     /**
377      * Does this list contain all ParameterNodes?
378      *
379      * @return boolean Whether or not the list contains all ParameterNodes
380      */

381     public boolean containsAllParameterNodes()
382     {
383         int size = size();
384
385         for (int index = 0; index < size; index++)
386         {
387             if (! (((ValueNode) elementAt(index)).requiresTypeFromContext()))
388             {
389                 return false;
390             }
391         }
392         return true;
393     }
394
395     /**
396      * Does this list contain all ConstantNodes?
397      *
398      * @return boolean Whether or not the list contains all ConstantNodes
399      */

400     public boolean containsAllConstantNodes()
401     {
402         int size = size();
403
404         for (int index = 0; index < size; index++)
405         {
406             if (! ((ValueNode) elementAt(index) instanceof ConstantNode))
407             {
408                 return false;
409             }
410         }
411         return true;
412     }
413
414     /**
415      * Sort the entries in the list in ascending order.
416      * (All values are assumed to be constants.)
417      *
418      * @param judgeODV In case of type not exactly matching, the judging type.
419      *
420      * @exception StandardException Thrown on error
421      */

422     void sortInAscendingOrder(DataValueDescriptor judgeODV)
423         throws StandardException
424     {
425         int size = size();
426
427         if (SanityManager.DEBUG)
428         {
429             SanityManager.ASSERT(size > 0,
430                 "size() expected to be non-zero");
431         }
432
433         /* We use bubble sort to sort the list since we expect
434          * the list to be in sorted order > 90% of the time.
435          */

436         boolean continueSort = true;
437
438         while (continueSort)
439         {
440             continueSort = false;
441             
442             for (int index = 1; index < size; index++)
443             {
444                 ConstantNode currCN = (ConstantNode) elementAt(index);
445                 DataValueDescriptor currODV =
446                      currCN.getValue();
447                 ConstantNode prevCN = (ConstantNode) elementAt(index - 1);
448                 DataValueDescriptor prevODV =
449                      prevCN.getValue();
450
451                 /* Swap curr and prev if prev > curr */
452                 if ((judgeODV == null && (prevODV.compare(currODV)) > 0) ||
453                     (judgeODV != null && judgeODV.greaterThan(prevODV, currODV).equals(true)))
454                 {
455                     setElementAt(currCN, index - 1);
456                     setElementAt(prevCN, index);
457                     continueSort = true;
458                 }
459             }
460         }
461     }
462
463     /**
464      * Set the descriptor for every ParameterNode in the list.
465      *
466      * @param descriptor The DataTypeServices to set for the parameters
467      *
468      * @exception StandardException Thrown on error
469      */

470     public void setParameterDescriptor(DataTypeDescriptor descriptor)
471                         throws StandardException
472     {
473         int size = size();
474         ValueNode valueNode;
475
476         for (int index = 0; index < size; index++)
477         {
478             valueNode = (ValueNode) elementAt(index);
479             if (valueNode.requiresTypeFromContext())
480             {
481                 valueNode.setType(descriptor);
482             }
483         }
484     }
485
486     /**
487      * Preprocess a ValueNodeList. For now, we just preprocess each ValueNode
488      * in the list.
489      *
490      * @param numTables Number of tables in the DML Statement
491      * @param outerFromList FromList from outer query block
492      * @param outerSubqueryList SubqueryList from outer query block
493      * @param outerPredicateList PredicateList from outer query block
494      *
495      * @exception StandardException Thrown on error
496      */

497     public void preprocess(int numTables,
498                             FromList outerFromList,
499                             SubqueryList outerSubqueryList,
500                             PredicateList outerPredicateList)
501         throws StandardException
502     {
503         int size = size();
504         ValueNode valueNode;
505
506         for (int index = 0; index < size; index++)
507         {
508             valueNode = (ValueNode) elementAt(index);
509             valueNode.preprocess(numTables,
510                                  outerFromList, outerSubqueryList,
511                                  outerPredicateList);
512         }
513     }
514
515     /**
516      * Remap all ColumnReferences in this tree to be clones of the
517      * underlying expression.
518      *
519      * @return ValueNodeList The remapped expression tree.
520      *
521      * @exception StandardException Thrown on error
522      */

523     public ValueNodeList remapColumnReferencesToExpressions()
524         throws StandardException
525     {
526         int size = size();
527
528         for (int index = 0; index < size; index++)
529         {
530             setElementAt(
531                 ((ValueNode) elementAt(index)).remapColumnReferencesToExpressions(),
532                 index);
533         }
534         return this;
535     }
536
537     /**
538      * Return whether or not this expression tree represents a constant expression.
539      *
540      * @return Whether or not this expression tree represents a constant expression.
541      */

542     public boolean isConstantExpression()
543     {
544         int size = size();
545
546         for (int index = 0; index < size; index++)
547         {
548             boolean retcode;
549
550             retcode = ((ValueNode) elementAt(index)).isConstantExpression();
551             if (! retcode)
552             {
553                 return retcode;
554             }
555         }
556
557         return true;
558     }
559
560     /** @see ValueNode#constantExpression */
561     public boolean constantExpression(PredicateList whereClause)
562     {
563         int size = size();
564
565         for (int index = 0; index < size; index++)
566         {
567             boolean retcode;
568
569             retcode =
570                 ((ValueNode) elementAt(index)).constantExpression(whereClause);
571             if (! retcode)
572             {
573                 return retcode;
574             }
575         }
576
577         return true;
578     }
579
580     /**
581      * Categorize this predicate. Initially, this means
582      * building a bit map of the referenced tables for each predicate.
583      * If the source of this ColumnReference (at the next underlying level)
584      * is not a ColumnReference or a VirtualColumnNode then this predicate
585      * will not be pushed down.
586      *
587      * For example, in:
588      * select * from (select 1 from s) a (x) where x = 1
589      * we will not push down x = 1.
590      * NOTE: It would be easy to handle the case of a constant, but if the
591      * inner SELECT returns an arbitrary expression, then we would have to copy
592      * that tree into the pushed predicate, and that tree could contain
593      * subqueries and method calls.
594      * RESOLVE - revisit this issue once we have views.
595      *
596      * @param referencedTabs JBitSet with bit map of referenced FromTables
597      * @param simplePredsOnly Whether or not to consider method
598      * calls, field references and conditional nodes
599      * when building bit map
600      *
601      * @return boolean Whether or not source.expression is a ColumnReference
602      * or a VirtualColumnNode.
603      * @exception StandardException Thrown on error
604      */

605     public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
606         throws StandardException
607     {
608         /* We stop here when only considering simple predicates
609          * as we don't consider in lists when looking
610          * for null invariant predicates.
611          */

612         boolean pushable = true;
613         int size = size();
614
615         for (int index = 0; index < size; index++)
616         {
617             pushable = ((ValueNode) elementAt(index)).categorize(referencedTabs, simplePredsOnly) &&
618                        pushable;
619         }
620
621         return pushable;
622     }
623
624     /**
625      * Return the variant type for the underlying expression.
626      * The variant type can be:
627      * VARIANT - variant within a scan
628      * (method calls and non-static field access)
629      * SCAN_INVARIANT - invariant within a scan
630      * (column references from outer tables)
631      * QUERY_INVARIANT - invariant within the life of a query
632      * CONSTANT - constant
633      *
634      * @return The variant type for the underlying expression.
635      * @exception StandardException thrown on error
636      */

637     protected int getOrderableVariantType() throws StandardException
638     {
639         int listType = Qualifier.CONSTANT;
640         int size = size();
641
642         /* If any element in the list is VARIANT then the
643          * entire expression is variant
644          * else it is SCAN_INVARIANT if any element is SCAN_INVARIANT
645          * else it is QUERY_INVARIANT.
646          */

647         for (int index = 0; index < size; index++)
648         {
649             int curType = ((ValueNode) elementAt(index)).getOrderableVariantType();
650             listType = Math.min(listType, curType);
651         }
652
653         return listType;
654     }
655 }
656
Popular Tags