KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ValueNode
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.types.DataTypeDescriptor;
25 import org.apache.derby.iapi.types.TypeId;
26 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
27 import org.apache.derby.iapi.error.StandardException;
28
29 import org.apache.derby.iapi.sql.compile.TypeCompiler;
30 import org.apache.derby.iapi.types.DataValueFactory;
31
32 import org.apache.derby.iapi.types.SQLChar;
33
34 import org.apache.derby.iapi.services.sanity.SanityManager;
35
36 import org.apache.derby.iapi.sql.compile.CompilerContext;
37 import org.apache.derby.iapi.sql.compile.Optimizable;
38 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
39 import org.apache.derby.iapi.sql.compile.NodeFactory;
40
41 import org.apache.derby.iapi.reference.SQLState;
42
43 import org.apache.derby.iapi.store.access.Qualifier;
44
45 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
46 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
47
48 import org.apache.derby.iapi.services.compiler.MethodBuilder;
49
50 import org.apache.derby.iapi.util.JBitSet;
51 import org.apache.derby.iapi.services.i18n.MessageService;
52
53 import java.lang.reflect.Modifier JavaDoc;
54
55 import java.sql.Date JavaDoc;
56 import java.sql.Time JavaDoc;
57 import java.sql.Timestamp JavaDoc;
58
59 import java.util.Vector JavaDoc;
60
61 /**
62  * A ValueNode is an abstract class for all nodes that can represent data
63  * values, that is, constants, columns, and expressions.
64  *
65  * @author Jeff Lichtman
66  */

67
68 public abstract class ValueNode extends QueryTreeNode
69 {
70     public static final int IN_UNKNOWN_CLAUSE = 0;
71     public static final int IN_SELECT_LIST = 1;
72     public static final int IN_WHERE_CLAUSE = 2;
73     public static final int IN_HAVING_CLAUSE = 3;
74
75     protected DataTypeDescriptor dataTypeServices;
76     private TypeId typeId;
77     private TypeCompiler typeCompiler;
78     protected int clause = IN_UNKNOWN_CLAUSE;
79
80     // Whether or not additional predicates have been created from this one.
81
boolean transformed;
82
83     /*
84     ** Constructor for untyped ValueNodes, for example, untyped NULLs
85     ** and parameter nodes.
86     **
87     ** Binding will replace all untyped ValueNodes with typed ValueNodes
88     ** when it figures out what their types should be.
89     */

90     public ValueNode()
91     {
92     }
93
94     /**
95      * Initializer for numeric types.
96      *
97      *
98      * @param typeId The TypeID of this new node
99      * @param precision The precision of this new node
100      * @param scale The scale of this new node
101      * @param isNullable The nullability of this new node
102      * @param maximumWidth The maximum width of this new node
103      *
104      * @exception StandardException
105      */

106
107     public void init(
108             Object JavaDoc typeId,
109             Object JavaDoc precision,
110             Object JavaDoc scale,
111             Object JavaDoc isNullable,
112             Object JavaDoc maximumWidth)
113         throws StandardException
114     {
115         setType(
116             new DataTypeDescriptor(
117                         (TypeId) typeId,
118                         ((Integer JavaDoc) precision).intValue(),
119                         ((Integer JavaDoc) scale).intValue(),
120                         ((Boolean JavaDoc) isNullable).booleanValue(),
121                         ((Integer JavaDoc) maximumWidth).intValue()
122                     )
123                 );
124     }
125
126     /**
127      * Initializer for non-numeric types.
128      *
129      *
130      * @param tcf The factory to get the
131      * DataTypeServicesFactory from
132      * @param typeId The TypeID of this new node
133      * @param isNullable The nullability of this new node
134      * @param maximumWidth The maximum width of this new node
135      *
136      * @exception StandardException
137      */

138
139     ValueNode(
140             Object JavaDoc tcf,
141             Object JavaDoc typeId,
142             Object JavaDoc isNullable,
143             Object JavaDoc maximumWidth)
144         throws StandardException
145     {
146         setType(new DataTypeDescriptor(
147                         (TypeId) typeId,
148                         ((Boolean JavaDoc) isNullable).booleanValue(),
149                         ((Integer JavaDoc) maximumWidth).intValue()
150                         )
151                 );
152     }
153
154             
155     /**
156      * Convert this object to a String. See comments in QueryTreeNode.java
157      * for how this should be done for tree printing.
158      *
159      * @return This object as a String
160      */

161
162     public String JavaDoc toString()
163     {
164         if (SanityManager.DEBUG)
165         {
166             return "dataTypeServices: " +
167                 ( ( dataTypeServices != null) ?
168                         dataTypeServices.toString() : "null" ) + "\n" +
169                 "clause: " + clause + "\n" +
170                 super.toString();
171         }
172         else
173         {
174             return "";
175         }
176     }
177
178     /**
179      * Get the DataTypeServices from this ValueNode.
180      *
181      * @return The DataTypeServices from this ValueNode. This
182      * may be null if the node isn't bound yet.
183      */

184     public DataTypeDescriptor getTypeServices() throws StandardException
185     {
186         return dataTypeServices;
187     }
188
189     /**
190      * Get the TypeId from this ValueNode.
191      *
192      * @return The TypeId from this ValueNode. This
193      * may be null if the node isn't bound yet.
194      */

195     public TypeId getTypeId() throws StandardException
196     {
197         return typeId;
198     }
199
200
201     /**
202         Return the DataValueFactory
203     */

204     protected final DataValueFactory getDataValueFactory() {
205         return getLanguageConnectionContext().getDataValueFactory();
206     }
207
208     /**
209      * Get the TypeCompiler from this ValueNode, based on its TypeId.
210      *
211      * @return This ValueNode's TypeCompiler
212      *
213      */

214     public TypeCompiler getTypeCompiler() throws StandardException
215     {
216         if (typeCompiler == null)
217         {
218             /*
219             ** getTypeId() is overriddend by parameter node so
220             ** don't get smart and remove the extra method call.
221             */

222             typeCompiler = getTypeCompiler(getTypeId());
223         }
224
225         return typeCompiler;
226     }
227
228     /**
229      * Set the DataTypeServices for this ValueNode. This method is
230      * overridden in ParameterNode.
231      *
232      * @param dataTypeServices The DataTypeServices to set in this
233      * ValueNode
234      */

235
236     public void setType(DataTypeDescriptor dataTypeServices) throws StandardException
237     {
238         this.dataTypeServices = dataTypeServices;
239
240         /* Get this now so we only have to cast it once */
241         if (dataTypeServices == null)
242             typeId = null;
243         else
244             typeId = dataTypeServices.getTypeId();
245
246         // Clear the typeCompiler, just in case type has changed
247
typeCompiler = null;
248     }
249
250
251     /**
252      * Get the source for this ValueNode.
253      *
254      * @return The source of this ValueNode.
255      */

256
257     public ResultColumn getSourceResultColumn()
258     {
259         if (SanityManager.DEBUG)
260         SanityManager.ASSERT(false,
261             "getSourceResultColumn() not expected to be called for this node - " +
262             getClass().toString());
263         return null;
264     }
265
266     /**
267      * Get the clause that this node appears in.
268      *
269      * @return int The clause that this node appears in.
270      */

271     public int getClause()
272     {
273         return clause;
274     }
275
276     /**
277      * Set the clause that this node appears in.
278      *
279      * @param clause The clause that this node appears in.
280      */

281     public void setClause(int clause)
282     {
283         this.clause = clause;
284     }
285
286     /**
287      * Mark this predicate has having been transformed (other predicates
288      * were generated from it). This will help us with ensure that the
289      * predicate does not get calculated into the selectivity multiple
290      * times.
291      */

292     void setTransformed()
293     {
294         transformed = true;
295     }
296
297     /**
298      * Return whether or not this predicate has been transformed.
299      *
300      * @return Whether or not this predicate has been transformed.
301      */

302     boolean getTransformed()
303     {
304         return transformed;
305     }
306
307     
308     public ValueNode bindExpression(
309                                     FromList fromList, SubqueryList subqueryList,
310                                     Vector JavaDoc aggregateVector)
311         throws StandardException
312     {
313         return bindExpression(fromList, subqueryList, aggregateVector,false);
314     }
315     
316
317     /**
318      * Bind this expression. This is a place-holder method - it should never
319      * be called.
320      *
321      * @param fromList The FROM list to use for binding
322      * @param subqueryList The SubqueryList we are building as we hit
323      * SubqueryNodes.
324      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
325      *
326      * @return The new top of the expression tree.
327      *
328      * @exception StandardException Thrown on error
329      */

330
331     public ValueNode bindExpression(
332             FromList fromList, SubqueryList subqueryList,
333             Vector JavaDoc aggregateVector, boolean forQueryRewrite)
334                 throws StandardException
335     {
336         /* There are a bizillion classes which extend ValueNode. Here is info
337          * on some of the classes that bindExpression() should not be called on
338          * and why:
339          * o BaseColumnNodes should only appear under the ResultColumnList
340          * in the FromBaseTable. They are created/bound when binding the
341          * FromBaseTable.
342          */

343         if (SanityManager.DEBUG)
344         {
345             SanityManager.ASSERT(false,
346                         "bindExpression() not expected to be called on a " +
347                         this.getClass().toString());
348         }
349
350         return this;
351     }
352
353     /**
354      * Generate a SQL->Java->SQL conversion tree above the current node
355      * and bind the new nodes individually.
356      * This is useful when doing comparisons, built-in functions, etc. on
357      * java types which have a direct mapping to system built-in types.
358      *
359      * @return ValueNode The new tree.
360      *
361      * @exception StandardException Thrown on error
362      */

363     public ValueNode genSQLJavaSQLTree()
364         throws StandardException
365     {
366         if (SanityManager.DEBUG)
367         {
368             SanityManager.ASSERT(typeId != null,
369                 "genSQLJavaSQLTree() only expected to be called on a bound node");
370             SanityManager.ASSERT(typeId.userType(),
371                 "genSQLJavaSQLTree() only expected to be called on user types");
372         }
373
374         JavaValueNode stjvn = (JavaValueNode) getNodeFactory().getNode(
375                                     C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
376                                     this,
377                                     getContextManager());
378
379         ValueNode jtsvn = (ValueNode) getNodeFactory().getNode(
380                                     C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
381                                     stjvn,
382                                     getContextManager());
383         jtsvn.setType(DataTypeDescriptor.getSQLDataTypeDescriptor(stjvn.getJavaTypeName()));
384         return jtsvn;
385     }
386
387     /**
388      * Preprocess an expression tree. We do a number of transformations
389      * here (including subqueries, IN lists, LIKE and BETWEEN) plus
390      * subquery flattening.
391      * NOTE: This is done before the outer ResultSetNode is preprocessed.
392      *
393      * @param numTables Number of tables in the DML Statement
394      * @param outerFromList FromList from outer query block
395      * @param outerSubqueryList SubqueryList from outer query block
396      * @param outerPredicateList PredicateList from outer query block
397      *
398      * @return The modified expression
399      *
400      * @exception StandardException Thrown on error
401      */

402     public ValueNode preprocess(int numTables,
403                                 FromList outerFromList,
404                                 SubqueryList outerSubqueryList,
405                                 PredicateList outerPredicateList)
406                     throws StandardException
407     {
408         return this;
409     }
410
411     /**
412      * Eliminate NotNodes in the current query block. We traverse the tree,
413      * inverting ANDs and ORs and eliminating NOTs as we go. We stop at
414      * ComparisonOperators and boolean expressions. We invert
415      * ComparisonOperators and replace boolean expressions with
416      * boolean expression = false.
417      * NOTE: Since we do not recurse under ComparisonOperators, there
418      * still could be NotNodes left in the tree.
419      *
420      * @param underNotNode Whether or not we are under a NotNode.
421      *
422      *
423      * @return The modified expression
424      *
425      * @exception StandardException Thrown on error
426      */

427     ValueNode eliminateNots(boolean underNotNode)
428                     throws StandardException
429     {
430         if (! underNotNode)
431         {
432             return this;
433         }
434
435         /* bind() has ensured that this node's type is SQLBoolean */
436         if (SanityManager.DEBUG)
437         SanityManager.ASSERT(
438                 dataTypeServices.getTypeId().equals(
439                                                 TypeId.BOOLEAN_ID),
440                     "Node's type (" +
441                     dataTypeServices.getTypeId().getSQLTypeName() +
442                     ") is expected to be boolean");
443
444         /* Return ValueNode = false */
445         return genEqualsFalseTree();
446     }
447
448     /**
449      * Transform this into this = false. Useful for NOT elimination.
450      *
451      *
452      * @return The modified expression
453      *
454      * @exception StandardException Thrown on error
455      */

456     public ValueNode genEqualsFalseTree()
457             throws StandardException
458     {
459         BinaryRelationalOperatorNode equalsNode;
460         BooleanConstantNode falseNode;
461         boolean nullableResult;
462         NodeFactory nodeFactory = getNodeFactory();
463
464         falseNode = (BooleanConstantNode) nodeFactory.getNode(
465                                     C_NodeTypes.BOOLEAN_CONSTANT_NODE,
466                                     Boolean.FALSE,
467                                     getContextManager());
468         equalsNode = (BinaryRelationalOperatorNode)
469                             nodeFactory.getNode(
470                                 C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,
471                                 this,
472                                 falseNode,
473                                 getContextManager());
474         nullableResult = dataTypeServices.isNullable();
475         equalsNode.setType(new DataTypeDescriptor(
476                                     TypeId.BOOLEAN_ID,
477                                     nullableResult)
478                           );
479         return equalsNode;
480     }
481
482     /**
483      * Transform this into this is null. Useful for NOT elimination.
484      *
485      * @return The modified expression
486      *
487      * @exception StandardException Thrown on error
488      */

489     public ValueNode genIsNullTree()
490             throws StandardException
491     {
492         IsNullNode isNullNode;
493
494         isNullNode = (IsNullNode)
495                             getNodeFactory().getNode(
496                                                     C_NodeTypes.IS_NULL_NODE,
497                                                     this,
498                                                     getContextManager());
499         isNullNode.setType(new DataTypeDescriptor(
500                                     TypeId.BOOLEAN_ID,
501                                     false)
502                           );
503         return isNullNode;
504     }
505
506     /**
507      * Verify that eliminateNots() did its job correctly. Verify that
508      * there are no NotNodes above the top level comparison operators
509      * and boolean expressions.
510      *
511      * @return Boolean which reflects validity of the tree.
512      */

513     boolean verifyEliminateNots()
514     {
515         if (SanityManager.ASSERT)
516         {
517             return (! (this instanceof NotNode));
518         }
519         else
520         {
521             return true;
522         }
523     }
524
525     /**
526      * Do the 1st step in putting an expression into conjunctive normal
527      * form. This step ensures that the top level of the expression is
528      * a chain of AndNodes.
529      *
530      * @return The modified expression
531      *
532      * @exception StandardException Thrown on error
533      */

534     public ValueNode putAndsOnTop()
535                     throws StandardException
536     {
537         NodeFactory nodeFactory = getNodeFactory();
538
539         QueryTreeNode trueNode = nodeFactory.getNode(
540                                         C_NodeTypes.BOOLEAN_CONSTANT_NODE,
541                                         Boolean.TRUE,
542                                         getContextManager());
543         AndNode andNode = (AndNode) nodeFactory.getNode(
544                                         C_NodeTypes.AND_NODE,
545                                         this,
546                                         trueNode,
547                                         getContextManager());
548         andNode.postBindFixup();
549         return andNode;
550     }
551
552     /**
553      * Verify that putAndsOnTop() did its job correctly. Verify that the top level
554      * of the expression is a chain of AndNodes.
555      *
556      * @return Boolean which reflects validity of the tree.
557      */

558     public boolean verifyPutAndsOnTop()
559     {
560         return true;
561     }
562
563     /**
564      * Finish putting an expression into conjunctive normal
565      * form. An expression tree in conjunctive normal form meets
566      * the following criteria:
567      * o If the expression tree is not null,
568      * the top level will be a chain of AndNodes terminating
569      * in a true BooleanConstantNode.
570      * o The left child of an AndNode will never be an AndNode.
571      * o Any right-linked chain that includes an AndNode will
572      * be entirely composed of AndNodes terminated by a true BooleanConstantNode.
573      * o The left child of an OrNode will never be an OrNode.
574      * o Any right-linked chain that includes an OrNode will
575      * be entirely composed of OrNodes terminated by a false BooleanConstantNode.
576      * o ValueNodes other than AndNodes and OrNodes are considered
577      * leaf nodes for purposes of expression normalization.
578      * In other words, we won't do any normalization under
579      * those nodes.
580      *
581      * In addition, we track whether or not we are under a top level AndNode.
582      * SubqueryNodes need to know this for subquery flattening.
583      *
584      * @param underTopAndNode Whether or not we are under a top level AndNode.
585      *
586      *
587      * @return The modified expression
588      *
589      * @exception StandardException Thrown on error
590      */

591     public ValueNode changeToCNF(boolean underTopAndNode)
592                     throws StandardException
593     {
594         return this;
595     }
596
597     /**
598      * Verify that changeToCNF() did its job correctly. Verify that:
599      * o AndNode - rightOperand is not instanceof OrNode
600      * leftOperand is not instanceof AndNode
601      * o OrNode - rightOperand is not instanceof AndNode
602      * leftOperand is not instanceof OrNode
603      *
604      * @return Boolean which reflects validity of the tree.
605      */

606     public boolean verifyChangeToCNF()
607     {
608         return true;
609     }
610
611     /**
612      * Categorize this predicate. Initially, this means
613      * building a bit map of the referenced tables for each predicate.
614      * If the source of this ColumnReference (at the next underlying level)
615      * is not a ColumnReference or a VirtualColumnNode then this predicate
616      * will not be pushed down.
617      *
618      * For example, in:
619      * select * from (select 1 from s) a (x) where x = 1
620      * we will not push down x = 1.
621      * NOTE: It would be easy to handle the case of a constant, but if the
622      * inner SELECT returns an arbitrary expression, then we would have to copy
623      * that tree into the pushed predicate, and that tree could contain
624      * subqueries and method calls.
625      * RESOLVE - revisit this issue once we have views.
626      *
627      * @param referencedTabs JBitSet with bit map of referenced FromTables
628      * @param simplePredsOnly Whether or not to consider method
629      * calls, field references and conditional nodes
630      * when building bit map
631      *
632      * @return boolean Whether or not source.expression is a ColumnReference
633      * or a VirtualColumnNode.
634      *
635      * @exception StandardException Thrown on error
636      */

637     public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
638         throws StandardException
639     {
640         return true;
641     }
642
643     /**
644      * This returns the user-supplied schema name of the column.
645      * At this class level, it simply returns null. But, the subclasses
646      * of ValueNode will overwrite this method to return the
647      * user-supplied schema name.
648      *
649      * When the value node is in a result column of a select list,
650      * the user can request metadata information. The result column
651      * won't have a column descriptor, so we return some default
652      * information through the expression. This lets expressions that
653      * are simply columns return all of the info, and others use
654      * this supertype's default values.
655      *
656      * @return the default schema name for an expression -- null
657      */

658     public String JavaDoc getSchemaName() throws StandardException
659     {
660         return null;
661     }
662
663     /**
664      * This returns the user-supplied table name of the column.
665      * At this class level, it simply returns null. But, the subclasses
666      * of ValueNode will overwrite this method to return the
667      * user-supplied table name.
668      *
669      * When the value node is in a result column of a select list,
670      * the user can request metadata information. The result column
671      * won't have a column descriptor, so we return some default
672      * information through the expression. This lets expressions that
673      * are simply columns return all of the info, and others use
674      * this supertype's default values.
675      *
676      * @return the default table name for an expression -- null
677      */

678     public String JavaDoc getTableName()
679     {
680         return null;
681     }
682
683     /**
684      * @return the default updatability for an expression - false
685      */

686     public boolean updatableByCursor()
687     {
688         return false;
689     }
690
691     /**
692      * This is null so that the caller will substitute in the resultset generated
693      * name as needed.
694      *
695      * @return the default column name for an expression -- null.
696      */

697     public String JavaDoc getColumnName()
698     {
699         return null;
700     }
701
702     /**
703      * Get a bit map of table references in this expression
704      *
705      * @return A bit map of table numbers referred to in this expression
706      *
707      * @exception StandardException Thrown on error
708      */

709     JBitSet getTablesReferenced()
710         throws StandardException
711     {
712         ReferencedTablesVisitor rtv = new ReferencedTablesVisitor(new JBitSet(0));
713         accept(rtv);
714         return rtv.getTableMap();
715     }
716
717     /**
718      * Return whether or not this expression tree is cloneable.
719      *
720      * @return boolean Whether or not this expression tree is cloneable.
721      */

722     public boolean isCloneable()
723     {
724         return false;
725     }
726
727     /**
728      * Return a clone of this node.
729      *
730      * @return ValueNode A clone of this node.
731      *
732      * @exception StandardException Thrown on error
733      */

734     public ValueNode getClone() throws StandardException
735     {
736         if (SanityManager.DEBUG)
737         {
738             SanityManager.ASSERT(false,
739                 "getClone() not expected to be called for " +
740                 getClass().getName());
741         }
742         return null;
743     }
744
745     /**
746      * Copy all of the "appropriate fields" for a shallow copy.
747      *
748      * @param oldVN The ValueNode to copy from.
749      *
750      */

751     public void copyFields(ValueNode oldVN) throws StandardException
752     {
753         dataTypeServices = oldVN.getTypeServices();
754         typeId = oldVN.getTypeId();
755     }
756
757     /**
758      * Remap all ColumnReferences in this tree to be clones of the
759      * underlying expression.
760      *
761      * @return ValueNode The remapped expression tree.
762      *
763      * @exception StandardException Thrown on error
764      */

765     public ValueNode remapColumnReferencesToExpressions() throws StandardException
766     {
767         return this;
768     }
769
770     /**
771      * Return whether or not this expression tree represents a constant expression.
772      *
773      * @return Whether or not this expression tree represents a constant expression.
774      */

775     public boolean isConstantExpression()
776     {
777         return false;
778     }
779
780     /**
781      * Return whether or not this expression tree represents a constant value.
782      * In this case, "constant" means that it will always evaluate to the
783      * same thing, even if it includes columns. A column is constant if it
784      * is compared to a constant expression.
785      *
786      * @return True means this expression tree represents a constant value.
787      */

788     public boolean constantExpression(PredicateList whereClause)
789     {
790         return false;
791     }
792
793     /**
794       * Bind time logic. Raises an error if this ValueNode, once compiled, returns
795       * unstable results AND if we're in a context where unstable results are
796       * forbidden.
797       *
798       * Called by children who may NOT appear in the WHERE subclauses of ADD TABLE clauses.
799       *
800       * @param fragmentType Type of fragment as a String, for inclusion in error messages.
801       * @param fragmentBitMask Type of fragment as a bitmask of possible fragment types
802       *
803       * @exception StandardException Thrown on error
804       */

805     public void checkReliability( String JavaDoc fragmentType, int fragmentBitMask )
806         throws StandardException
807     {
808         // if we're in a context that forbids unreliable fragments, raise an error
809
if ( ( getCompilerContext().getReliability() & fragmentBitMask ) != 0 )
810         {
811             throwReliabilityException( fragmentType );
812         }
813     }
814
815     /**
816       * Bind time logic. Raises an error if this ValueNode, once compiled, returns
817       * unstable results AND if we're in a context where unstable results are
818       * forbidden.
819       *
820       * Called by children who may NOT appear in the WHERE subclauses of ADD TABLE clauses.
821       *
822       * @param fragmentBitMask Type of fragment as a bitmask of possible fragment types
823       * @param fragmentType Type of fragment as a String, to be fetch for the error message.
824       *
825       * @exception StandardException Thrown on error
826       */

827     public void checkReliability( int fragmentBitMask, String JavaDoc fragmentType )
828         throws StandardException
829     {
830         // if we're in a context that forbids unreliable fragments, raise an error
831
if ( ( getCompilerContext().getReliability() & fragmentBitMask ) != 0 )
832         {
833             String JavaDoc fragmentTypeTxt = MessageService.getTextMessage( fragmentType );
834             throwReliabilityException( fragmentTypeTxt );
835         }
836     }
837
838     /**
839      * Common code for the 2 checkReliability functions. Always throws StandardException.
840      *
841      * @param fragmentType Type of fragment as a string, for inclusion in error messages.
842      * @exception StandardException Throws an error, always.
843      */

844     private void throwReliabilityException( String JavaDoc fragmentType ) throws StandardException
845     {
846         String JavaDoc sqlState;
847         /* Error string somewhat dependent on operation due to different
848          * nodes being allowed for different operations.
849          */

850         if (getCompilerContext().getReliability() == CompilerContext.DEFAULT_RESTRICTION)
851         {
852             sqlState = SQLState.LANG_INVALID_DEFAULT_DEFINITION;
853         }
854         else
855         {
856             sqlState = SQLState.LANG_UNRELIABLE_QUERY_FRAGMENT;
857         }
858         throw StandardException.newException(sqlState, fragmentType);
859     }
860
861     /**
862      * Return the variant type for the underlying expression.
863      * The variant type can be:
864      * VARIANT - variant within a scan
865      * (method calls and non-static field access)
866      * SCAN_INVARIANT - invariant within a scan
867      * (column references from outer tables)
868      * QUERY_INVARIANT - invariant within the life of a query
869      * (constant expressions)
870      *
871      * @return The variant type for the underlying expression.
872      * @exception StandardException Thrown on error
873      */

874     protected int getOrderableVariantType() throws StandardException
875     {
876         // The default is VARIANT
877
return Qualifier.VARIANT;
878     }
879
880
881     /**
882       * Bind time logic. Raises an error if this ValueNode does not resolve to
883       * a boolean value. This method is called by WHERE clauses.
884       *
885       * @return bound coercion of this node to a builtin type as necessary
886       *
887       * @exception StandardException Thrown on error
888       */

889     public ValueNode checkIsBoolean()
890         throws StandardException
891     {
892         ValueNode whereClause = this;
893
894         /*
895         ** Is the datatype of the WHERE clause BOOLEAN?
896         **
897         ** NOTE: This test is not necessary in SQL92 entry level, because
898         ** it is syntactically impossible to have a non-Boolean WHERE clause
899         ** in that level of the standard. But we intend to extend the
900         ** language to allow Boolean user functions in the WHERE clause,
901         ** so we need to test for the error condition.
902         */

903         TypeId whereTypeId = whereClause.getTypeId();
904
905         /* If the where clause is not a built-in type, then generate a bound
906          * conversion tree to a built-in type.
907          */

908         if (whereTypeId.userType())
909         {
910             whereClause = whereClause.genSQLJavaSQLTree();
911             whereTypeId = whereClause.getTypeId();
912         }
913
914         if (! whereTypeId.equals(TypeId.BOOLEAN_ID))
915         {
916             throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE,
917                 whereTypeId.getSQLTypeName()
918                 );
919         }
920
921         return whereClause;
922     }
923
924     /**
925      * Return an Object representing the bind time value of this
926      * expression tree. If the expression tree does not evaluate to
927      * a constant at bind time then we return null.
928      * This is useful for bind time resolution of VTIs.
929      * RESOLVE: What do we do for primitives?
930      *
931      * @return An Object representing the bind time value of this expression tree.
932      * (null if not a bind time constant.)
933      *
934      * @exception StandardException Thrown on error
935      */

936     Object JavaDoc getConstantValueAsObject()
937         throws StandardException
938     {
939         return null;
940     }
941
942     /////////////////////////////////////////////////////////////////////////
943
//
944
// The ValueNode defers its generate() work to a method that works on
945
// ExpressionClassBuilders rather than ActivationClassBuilders. This
946
// is so that expression generation can be shared by the Core compiler
947
// AND the Replication Filter compiler.
948
//
949
/////////////////////////////////////////////////////////////////////////
950

951
952     /**
953      * Do the code generation for this node. Call the more general
954      * routine that generates expressions.
955      *
956      * @param acb The ActivationClassBuilder for the class being built
957      * @param mb The method the expression will go into
958      *
959      *
960      * @exception StandardException Thrown on error
961      */

962
963     protected final void generate(ActivationClassBuilder acb,
964                                         MethodBuilder mb)
965                                 throws StandardException
966     {
967         generateExpression( acb, mb );
968     }
969
970     /**
971      * The only reason this routine exists is so that I don't have to change
972      * the protection on generateExpression() and rototill all of QueryTree.
973      *
974      * @param ecb The ExpressionClassBuilder for the class being built
975      * @param mb The method the expression will go into
976      *
977      *
978      * @exception StandardException Thrown on error
979      */

980     public void generateFilter(ExpressionClassBuilder ecb,
981                                         MethodBuilder mb)
982         throws StandardException
983     {
984         generateExpression( ecb, mb );
985     }
986     
987
988     /**
989      * The default selectivity for value nodes is 50%. This is overridden
990      * in specific cases, such as the RelationalOperators.
991      */

992     public double selectivity(Optimizable optTable)
993     throws StandardException
994     {
995         // Return 1 if additional predicates have been generated from this one.
996
if (transformed)
997         {
998             return 1.0;
999         }
1000        else
1001        {
1002            return 0.5d;
1003        }
1004    }
1005
1006    /**
1007     * Update the array of columns in = conditions with expressions without
1008     * column references from the same table. This is useful when doing
1009     * subquery flattening on the basis of an equality condition.
1010     * eqOuterCols or tableColMap may be null if the calling routine
1011     * doesn't need the information provided
1012     *
1013     * @param tableNumber The tableNumber of the table from which
1014     * the columns of interest come from.
1015     * @param eqOuterCols Array of booleans for noting which columns
1016     * are in = predicates without columns from the
1017     * subquery block. May be null.
1018     * @param tableNumbers Array of table numbers in this query block.
1019     * @param tableColMap Array of bits for noting which columns
1020     * are in = predicates for each table in the
1021     * query block. May be null.
1022     * @param resultColTable True if tableNumber is the table containing result
1023     * columns
1024     *
1025     * @exception StandardException Thrown on error
1026     *
1027     */

1028    void checkTopPredicatesForEqualsConditions(
1029                int tableNumber, boolean[] eqOuterCols, int[] tableNumbers,
1030                JBitSet[] tableColMap, boolean resultColTable)
1031        throws StandardException
1032    {
1033        for (ValueNode whereWalker = this; whereWalker instanceof AndNode;
1034             whereWalker = ((AndNode) whereWalker).getRightOperand())
1035        {
1036            // See if this is a candidate =
1037
AndNode and = (AndNode) whereWalker;
1038
1039            if (!and.getLeftOperand().isRelationalOperator() ||
1040                !(((RelationalOperator)(and.getLeftOperand())).getOperator() == RelationalOperator.EQUALS_RELOP))
1041            {
1042                continue;
1043            }
1044
1045            BinaryRelationalOperatorNode beon =
1046                    (BinaryRelationalOperatorNode) and.getLeftOperand();
1047            ValueNode left = beon.getLeftOperand();
1048            ValueNode right = beon.getRightOperand();
1049            int resultTable = 0;
1050            if (resultColTable)
1051            {
1052                for ( ; resultTable < tableNumbers.length; resultTable++)
1053                {
1054                    if (tableNumbers[resultTable] == tableNumber)
1055                        break;
1056                }
1057            }
1058            else
1059                resultTable = -1;
1060
1061            /* Is this = of the right form? */
1062            if ((left instanceof ColumnReference) &&
1063                ((ColumnReference) left).getTableNumber() == tableNumber)
1064            {
1065                updateMaps(tableColMap, eqOuterCols, tableNumbers, tableNumber,
1066                    resultTable, right, left);
1067            }
1068            else if ((right instanceof ColumnReference) &&
1069                     ((ColumnReference) right).getTableNumber() == tableNumber)
1070            {
1071                updateMaps(tableColMap, eqOuterCols, tableNumbers, tableNumber,
1072                    resultTable, left, right);
1073            }
1074        }
1075    }
1076
1077    /**
1078     * Does this represent a true constant.
1079     *
1080     * @return Whether or not this node represents a true constant.
1081     */

1082    boolean isBooleanTrue()
1083    {
1084        return false;
1085    }
1086
1087    /**
1088     * Does this represent a false constant.
1089     *
1090     * @return Whether or not this node represents a false constant.
1091     */

1092    boolean isBooleanFalse()
1093    {
1094        return false;
1095    }
1096
1097    /**
1098     * Generate code for this calculation. This is a place-holder method -
1099     * it should not be called.
1100     *
1101     * @param acb The ExpressionClassBuilder for the class being built
1102     * @param mb The method the expression will go into
1103     *
1104     *
1105     * @exception StandardException Thrown on error
1106     */

1107
1108    public void generateExpression(ExpressionClassBuilder acb,
1109                                            MethodBuilder mb)
1110                        throws StandardException
1111    {
1112        if (SanityManager.DEBUG)
1113        SanityManager.ASSERT(false, "Code generation for this type of ValueNode is unimplemented");
1114    }
1115
1116    /**
1117     * Set the correct bits in tableColMap and set the boolean value in eqOuterCols
1118     * given two arguments to an = predicate
1119     * tableColMap[t] - bit is set if the column is in an = predicate with a column
1120     * in table t, or a bit is set if the column is in an
1121     * = predicate with a constant,parameter or correlation variable
1122     * (for all table t, if this tableColMap is not for the
1123     * table with the result columns)
1124     * eqOuterCols[c] - is true if the column is in an = predicate with a constant,
1125     * parameter or correlation variable
1126     *
1127     *
1128     * @param tableColMap Array of bitmaps for noting which columns are in =
1129     * predicates with columns from each table
1130     * @param eqOuterCols Array of booleans for noting which columns
1131     * are in = predicates without columns from the
1132     * subquery block.
1133     * @param tableNumber table number for which we are setting up the Maps
1134     * @param resultTable -1 if this table is not the result table; otherwise
1135     * the index into tableNumbers for the result table
1136     * @param arg1 one side of the = predicate
1137     * @param arg2 other side of the = predicate
1138     *
1139     *
1140     * @exception StandardException Thrown on error
1141     */

1142    private void updateMaps(JBitSet[] tableColMap, boolean[] eqOuterCols,
1143        int[] tableNumbers, int tableNumber, int resultTable,
1144        ValueNode arg1, ValueNode arg2)
1145            throws StandardException
1146    {
1147        /* arg2 is a column from our table. This
1148         * is a good = for both All tables and Outer arrays
1149         * if the right side is a constant or a parameter
1150         * or a column from an outer table.
1151         * It is a good = for only the All array if
1152         * the right side is a column from this query block.
1153         */

1154        if ((arg1 instanceof ConstantNode) || (arg1.requiresTypeFromContext()))
1155        {
1156            setValueCols(tableColMap, eqOuterCols,
1157                ((ColumnReference) arg2).getColumnNumber(), resultTable);
1158        }
1159        else if((arg1 instanceof ColumnReference &&
1160                    ((ColumnReference) arg1).getTableNumber() != tableNumber))
1161        {
1162            /* See if other columns is a correlation column */
1163            int otherTN = ((ColumnReference) arg1).getTableNumber();
1164            int index = 0;
1165            int colNumber = ((ColumnReference) arg2).getColumnNumber();
1166
1167            for ( ; index < tableNumbers.length; index++)
1168            {
1169                if (otherTN == tableNumbers[index])
1170                {
1171                    break;
1172                }
1173            }
1174            /* Correlation column, so we can treat it as a constant */
1175            if (index == tableNumbers.length)
1176            {
1177                setValueCols(tableColMap, eqOuterCols, colNumber, resultTable);
1178            }
1179            else if (tableColMap != null)
1180            {
1181                tableColMap[index].set(colNumber);
1182            }
1183
1184        }
1185        else
1186        {
1187            /* See if other side contains a column reference from the same table */
1188            JBitSet referencedTables = arg1.getTablesReferenced();
1189            /* See if other columns are all correlation columns */
1190            int index = 0;
1191            int colNumber = ((ColumnReference) arg2).getColumnNumber();
1192            for ( ; index < tableNumbers.length; index++)
1193            {
1194                if (referencedTables.get(tableNumbers[index]))
1195                {
1196                    break;
1197                }
1198            }
1199            /* Correlation column, so we can treat it as a constant */
1200            if (index == tableNumbers.length)
1201            {
1202                setValueCols(tableColMap, eqOuterCols, colNumber, resultTable);
1203            }
1204            else if (tableColMap != null && !referencedTables.get(tableNumber))
1205            {
1206                tableColMap[index].set(colNumber);
1207            }
1208        }
1209    }
1210    /**
1211     * Set eqOuterCols and the column in all the tables for constants,
1212     * parmeters and correlation columns
1213     * The column in the tableColMap is set only for the current table
1214     * if the table is the result column table. For other tables in the
1215     * query we set the column for all the tables since the constant will
1216     * reduced the number of columns required in a unique multicolumn index for
1217     * distinctness.
1218     * For example, given an unique index on t1(a,b), setting b=1 means that
1219     * t1(a) is unique since there can be no duplicates for a where b=1 without
1220     * destroying the uniqueness of t1(a,b). However, for the result columns
1221     * setting b=1, does not mean that a select list of t1.a is distinct if
1222     * t1.a is the only column used in joining with another table
1223     * e.g. select t1.a from t1, t2 where t1.a = t2.a and t1.b = 1;
1224     *
1225     * t1 t2 result
1226     * a b a a
1227     * 1 1 1 1
1228     * 1 2 2 1
1229     * 2 1
1230     *
1231     *
1232     * @param tableColMap Array of bitmaps for noting which columns are in =
1233     * predicates with columns from each table
1234     * @param eqOuterCols Array of booleans for noting which columns
1235     * are in = predicates without columns from the
1236     * subquery block.
1237     * @param colReference The column to set
1238     * @param resultTable If -1 set all the bit for all the tables for that
1239     * column; otherwise set the bit for the specified table
1240     *
1241     *
1242     */

1243    private void setValueCols(JBitSet[] tableColMap, boolean[] eqOuterCols,
1244        int colReference, int resultTable)
1245    {
1246        if (eqOuterCols != null)
1247            eqOuterCols[colReference] = true;
1248
1249        if (tableColMap != null)
1250        {
1251            if (resultTable == -1)
1252            {
1253                for (int i = 0; i < tableColMap.length; i++)
1254                    tableColMap[i].set(colReference);
1255            }
1256            else
1257                tableColMap[resultTable].set(colReference);
1258        }
1259    }
1260
1261    /**
1262     * Returns true if this ValueNode is a relational operator. Relational
1263     * Operators are <, <=, =, >, >=, <> as well as IS NULL and IS NOT
1264     * NULL. This is the preferred way of figuring out if a ValueNode is
1265     * relational or not.
1266     * @see RelationalOperator
1267     * @see BinaryRelationalOperatorNode
1268     * @see IsNullNode
1269    */

1270    public boolean isRelationalOperator()
1271    {
1272        return false;
1273    }
1274    
1275    /**
1276     * Returns true if this value node is a <em>equals</em> operator.
1277     *
1278     * @see ValueNode#isRelationalOperator
1279     */

1280    public boolean isBinaryEqualsOperatorNode()
1281    {
1282        return false;
1283    }
1284
1285    /** Return true if the predicate represents an optimizable equality node.
1286     * an expression is considered to be an optimizable equality node if all the
1287     * following conditions are met:
1288     * <ol>
1289     * <li> the operator is an <em>=</em> or <em>IS NULL</em> operator </li>
1290     * <li> one of the operands is a column specified by optTable/columnNumber</li>
1291     * <li> Both operands are not the same column; i.e tab.col = tab.col </li>
1292     * <li> There are no implicit varchar comparisons of the operands; i.e
1293     * either both operands are string like (varchar, char, longvarchar) or
1294     * neither operand is string like </li>
1295     * </ol>
1296     *
1297     * @param optTable the table being optimized. Column reference must be from
1298     * this table.
1299     * @param columnNumber the column number. One of the operands of this
1300     * predicate must be the column number specified by optTable/columnNumber
1301     * @param isNullOkay if set to true we also consider IS NULL predicates;
1302     * otherwise consider only = predicates.
1303     */

1304    public boolean optimizableEqualityNode(Optimizable optTable,
1305                                           int columnNumber,
1306                                           boolean isNullOkay)
1307        throws StandardException
1308    {
1309        return false;
1310    }
1311
1312    /**
1313     * Returns TRUE if the type of this node will be determined from the
1314     * context in which it is getting used.
1315     *
1316     * @return Whether this node's type will be determined from the context
1317     */

1318    public boolean requiresTypeFromContext()
1319    {
1320        return false;
1321    }
1322
1323    /**
1324     * Returns TRUE if this is a parameter node. We do lots of special things
1325     * with Parameter Nodes.
1326     *
1327     */

1328    public boolean isParameterNode()
1329    {
1330        return false;
1331    }
1332    
1333    /**
1334     * Tests if this node is equivalent to the specified ValueNode. Two
1335     * ValueNodes are considered equivalent if they will evaluate to the same
1336     * value during query execution.
1337     * <p>
1338     * This method provides basic expression matching facility for the derived
1339     * class of ValueNode and it is used by the language layer to compare the
1340     * node structural form of the two expressions for equivalence at bind
1341     * phase.
1342     * <p>
1343     * Note that it is not comparing the actual row values at runtime to produce
1344     * a result; hence, when comparing SQL NULLs, they are considered to be
1345     * equivalent and not unknown.
1346     * <p>
1347     * One usage case of this method in this context is to compare the select
1348     * column expression against the group by expression to check if they are
1349     * equivalent. e.g.:
1350     * <p>
1351     * SELECT c1+c2 FROM t1 GROUP BY c1+c2
1352     * <p>
1353     * In general, node equivalence is determined by the derived class of
1354     * ValueNode. But they generally abide to the rules below:
1355     * <ul>
1356     * <li>The two ValueNodes must be of the same node type to be considered
1357     * equivalent. e.g.: CastNode vs. CastNode - equivalent (if their args
1358     * also match), ColumnReference vs CastNode - not equivalent.
1359     *
1360     * <li>If node P contains other ValueNode(s) and so on, those node(s) must
1361     * also be of the same node type to be considered equivalent.
1362     *
1363     * <li>If node P takes a parameter list, then the number of arguments and its
1364     * arguments for the two nodes must also match to be considered
1365     * equivalent. e.g.: CAST(c1 as INTEGER) vs CAST(c1 as SMALLINT), they
1366     * are not equivalent.
1367     *
1368     * <li>When comparing SQL NULLs in this context, they are considered to be
1369     * equivalent.
1370     *
1371     * <li>If this does not apply or it is determined that the two nodes are not
1372     * equivalent then the derived class of this method should return false;
1373     * otherwise, return true.
1374     * </ul>
1375     *
1376     * @param other the node to compare this ValueNode against.
1377     * @return <code>true</code> if the two nodes are equivalent,
1378     * <code>false</code> otherwise.
1379     *
1380     * @throws StandardException
1381     */

1382    protected abstract boolean isEquivalent(ValueNode other)
1383        throws StandardException;
1384
1385    /**
1386     * Tests if this node is of the same type as the specified node as
1387     * reported by {@link QueryTreeNode#getNodeType()}.
1388     *
1389     * @param other the node to compare this value node against.
1390     *
1391     * @return <code>true</code> if the two nodes are of the same type.
1392     */

1393    protected final boolean isSameNodeType(ValueNode other)
1394    {
1395        if (other != null) {
1396            return other.getNodeType() == getNodeType();
1397        }
1398        return false;
1399    }
1400    
1401}
1402
Popular Tags