KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.BinaryRelationalOperatorNode
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.ClassName;
25 import org.apache.derby.iapi.reference.JDBC30Translation;
26
27 import org.apache.derby.iapi.util.JBitSet;
28
29 import org.apache.derby.iapi.services.loader.GeneratedMethod;
30
31 import org.apache.derby.iapi.services.compiler.MethodBuilder;
32
33 import org.apache.derby.iapi.services.sanity.SanityManager;
34
35 import org.apache.derby.iapi.error.StandardException;
36
37 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
38 import org.apache.derby.iapi.sql.compile.Optimizable;
39
40 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
41
42 import org.apache.derby.iapi.store.access.Qualifier;
43 import org.apache.derby.iapi.store.access.ScanController;
44
45 import org.apache.derby.iapi.types.DataValueDescriptor;
46 import org.apache.derby.iapi.types.TypeId;
47 import org.apache.derby.iapi.types.DataValueDescriptor;
48
49 import org.apache.derby.iapi.types.Orderable;
50
51 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
52
53 import java.sql.Types JavaDoc;
54
55 /**
56  * This class represents the 6 binary operators: LessThan, LessThanEquals,
57  * Equals, NotEquals, GreaterThan and GreaterThanEquals.
58  *
59  * @author Manish Khettry
60  */

61
62 public class BinaryRelationalOperatorNode
63     extends BinaryComparisonOperatorNode
64     implements RelationalOperator
65 {
66     private int operatorType;
67     /* RelationalOperator Interface */
68
69     // Visitor for finding base tables beneath optimizables and column
70
// references. Created once and re-used thereafter.
71
private BaseTableNumbersVisitor btnVis;
72
73     // Bit sets for holding base tables beneath optimizables and
74
// column references. Created once and re-used thereafter.
75
JBitSet optBaseTables;
76     JBitSet valNodeBaseTables;
77
78     public void init(Object JavaDoc leftOperand, Object JavaDoc rightOperand)
79     {
80         String JavaDoc methodName = "";
81         String JavaDoc operatorName = "";
82
83         switch (getNodeType())
84         {
85             case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE:
86                 methodName = "equals";
87                 operatorName = "=";
88                 operatorType = RelationalOperator.EQUALS_RELOP;
89                 break;
90
91             case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE:
92                 methodName = "greaterOrEquals";
93                 operatorName = ">=";
94                 operatorType = RelationalOperator.GREATER_EQUALS_RELOP;
95                 break;
96
97             case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE:
98                 methodName = "greaterThan";
99                 operatorName = ">";
100                 operatorType = RelationalOperator.GREATER_THAN_RELOP;
101                 break;
102
103             case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE:
104                 methodName = "lessOrEquals";
105                 operatorName = "<=";
106                 operatorType = RelationalOperator.LESS_EQUALS_RELOP;
107                 break;
108
109             case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE:
110                 methodName = "lessThan";
111                 operatorName = "<";
112                 operatorType = RelationalOperator.LESS_THAN_RELOP;
113                 break;
114             case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE:
115                 methodName = "notEquals";
116                 operatorName = "<>";
117                 operatorType = RelationalOperator.NOT_EQUALS_RELOP;
118                 break;
119
120             default:
121                 if (SanityManager.DEBUG)
122                 {
123                     SanityManager.THROWASSERT("init for BinaryRelationalOperator called with wrong nodeType = " + getNodeType());
124                 }
125                 break;
126         }
127         super.init(leftOperand, rightOperand, operatorName, methodName);
128         btnVis = null;
129     }
130
131     /** @see RelationalOperator#getColumnOperand */
132     public ColumnReference getColumnOperand(
133                                 Optimizable optTable,
134                                 int columnPosition)
135     {
136         FromTable ft = (FromTable) optTable;
137
138         // When searching for a matching column operand, we search
139
// the entire subtree (if there is one) beneath optTable
140
// to see if we can find any FromTables that correspond to
141
// either of this op's column references.
142

143         ColumnReference cr;
144         boolean walkSubtree = true;
145         if (leftOperand instanceof ColumnReference)
146         {
147             /*
148             ** The left operand is a column reference.
149             ** Is it the correct column?
150             */

151             cr = (ColumnReference) leftOperand;
152             if (valNodeReferencesOptTable(cr, ft, false, walkSubtree))
153             {
154                 /*
155                 ** The table is correct, how about the column position?
156                 */

157                 if (cr.getSource().getColumnPosition() == columnPosition)
158                 {
159                     /* We've found the correct column - return it */
160                     return cr;
161                 }
162             }
163             walkSubtree = false;
164         }
165
166         if (rightOperand instanceof ColumnReference)
167         {
168             /*
169             ** The right operand is a column reference.
170             ** Is it the correct column?
171             */

172             cr = (ColumnReference) rightOperand;
173             if (valNodeReferencesOptTable(cr, ft, false, walkSubtree))
174             {
175                 /*
176                 ** The table is correct, how about the column position?
177                 */

178                 if (cr.getSource().getColumnPosition() == columnPosition)
179                 {
180                     /* We've found the correct column - return it */
181                     return cr;
182                 }
183             }
184         }
185
186         /* Neither side is the column we're looking for */
187         return null;
188     }
189
190     /** @see RelationalOperator#getColumnOperand */
191     public ColumnReference getColumnOperand(Optimizable optTable)
192     {
193         ColumnReference cr;
194
195         boolean walkSubtree = true;
196         if (leftOperand instanceof ColumnReference)
197         {
198             /*
199             ** The left operand is a column reference.
200             ** Is it the correct column?
201             */

202             cr = (ColumnReference) leftOperand;
203             if (valNodeReferencesOptTable(
204                 cr, (FromTable)optTable, false, walkSubtree))
205             {
206                 /*
207                 ** The table is correct.
208                 */

209                 return cr;
210             }
211             walkSubtree = false;
212         }
213
214         if (rightOperand instanceof ColumnReference)
215         {
216             /*
217             ** The right operand is a column reference.
218             ** Is it the correct column?
219             */

220             cr = (ColumnReference) rightOperand;
221             if (valNodeReferencesOptTable(cr,
222                 (FromTable)optTable, false, walkSubtree))
223             {
224                 /*
225                 ** The table is correct
226                 */

227                 return cr;
228             }
229         }
230
231         /* Neither side is the column we're looking for */
232         return null;
233     }
234
235     /**
236      * @see RelationalOperator#getExpressionOperand
237      */

238     public ValueNode getExpressionOperand(
239                                 int tableNumber,
240                                 int columnPosition,
241                                 FromTable ft)
242     {
243         ColumnReference cr;
244         boolean walkSubtree = true;
245
246         if (leftOperand instanceof ColumnReference)
247         {
248             /*
249             ** The left operand is a column reference.
250             ** Is it the correct column?
251             */

252             cr = (ColumnReference) leftOperand;
253             if (valNodeReferencesOptTable(cr, ft, false, walkSubtree))
254             {
255                 /*
256                 ** The table is correct, how about the column position?
257                 */

258                 if (cr.getSource().getColumnPosition() == columnPosition)
259                 {
260                     /*
261                     ** We've found the correct column -
262                     ** return the other side
263                     */

264                     return rightOperand;
265                 }
266             }
267             walkSubtree = false;
268         }
269
270         if (rightOperand instanceof ColumnReference)
271         {
272             /*
273             ** The right operand is a column reference.
274             ** Is it the correct column?
275             */

276             cr = (ColumnReference) rightOperand;
277             if (valNodeReferencesOptTable(cr, ft, false, walkSubtree))
278             {
279                 /*
280                 ** The table is correct, how about the column position?
281                 */

282                 if (cr.getSource().getColumnPosition() == columnPosition)
283                 {
284                     /*
285                     ** We've found the correct column -
286                     ** return the other side
287                     */

288                     return leftOperand;
289                 }
290             }
291         }
292
293         return null;
294     }
295
296     /**
297      * @see RelationalOperator#getOperand
298      */

299     public ValueNode getOperand(ColumnReference cRef,
300         int refSetSize, boolean otherSide)
301     {
302         // Following call will initialize/reset the btnVis,
303
// valNodeBaseTables, and optBaseTables fields of this object.
304
initBaseTableVisitor(refSetSize, true);
305
306         // We search for the column reference by getting the *base*
307
// table number for each operand and checking to see if
308
// that matches the *base* table number for the cRef
309
// that we're looking for. If so, then we the two
310
// reference the same table so we go on to check
311
// column position.
312
try {
313
314             // Use optBaseTables for cRef's base table numbers.
315
btnVis.setTableMap(optBaseTables);
316             cRef.accept(btnVis);
317
318             // Use valNodeBaseTables for operand base table nums.
319
btnVis.setTableMap(valNodeBaseTables);
320
321             ColumnReference cr;
322             if (leftOperand instanceof ColumnReference)
323             {
324                 /*
325                 ** The left operand is a column reference.
326                 ** Is it the correct column?
327                 */

328                 cr = (ColumnReference) leftOperand;
329                 cr.accept(btnVis);
330                 valNodeBaseTables.and(optBaseTables);
331                 if (valNodeBaseTables.getFirstSetBit() != -1)
332                 {
333                     /*
334                     ** The table is correct, how about the column position?
335                     */

336                     if (cr.getSource().getColumnPosition() ==
337                         cRef.getColumnNumber())
338                     {
339                         /*
340                         ** We've found the correct column -
341                         ** return the appropriate side.
342                         */

343                         if (otherSide)
344                             return rightOperand;
345                         return leftOperand;
346                     }
347                 }
348             }
349
350             if (rightOperand instanceof ColumnReference)
351             {
352                 /*
353                 ** The right operand is a column reference.
354                 ** Is it the correct column?
355                 */

356                 valNodeBaseTables.clearAll();
357                 cr = (ColumnReference) rightOperand;
358                 cr.accept(btnVis);
359                 valNodeBaseTables.and(optBaseTables);
360                 if (valNodeBaseTables.getFirstSetBit() != -1)
361                 {
362                     /*
363                     ** The table is correct, how about the column position?
364                     */

365                     if (cr.getSource().getColumnPosition() ==
366                         cRef.getColumnNumber())
367                     {
368                         /*
369                         ** We've found the correct column -
370                         ** return the appropriate side
371                         */

372                         if (otherSide)
373                             return leftOperand;
374                         return rightOperand;
375                     }
376                 }
377             }
378
379         } catch (StandardException se) {
380             if (SanityManager.DEBUG)
381             {
382                 SanityManager.THROWASSERT("Failed when trying to " +
383                     "find base table number for column reference check:\n" +
384                     se.getMessage());
385             }
386         }
387
388         return null;
389     }
390
391     /**
392      * @see RelationalOperator#generateExpressionOperand
393      *
394      * @exception StandardException Thrown on error
395      */

396     public void generateExpressionOperand(
397                                 Optimizable optTable,
398                                 int columnPosition,
399                                 ExpressionClassBuilder acb,
400                                 MethodBuilder mb)
401                         throws StandardException
402     {
403         ColumnReference cr;
404         FromBaseTable ft;
405
406         if (SanityManager.DEBUG)
407         {
408             SanityManager.ASSERT(optTable instanceof FromBaseTable);
409         }
410         ft = (FromBaseTable) optTable;
411
412         ValueNode exprOp = getExpressionOperand(
413             ft.getTableNumber(), columnPosition, ft);
414
415         if (SanityManager.DEBUG)
416         {
417             if (exprOp == null)
418             {
419                 SanityManager.THROWASSERT(
420                     "ColumnReference for correct column (columnPosition = " +
421                     columnPosition +
422                     ", exposed table name = " + ft.getExposedName() +
423                 ") not found on either side of BinaryRelationalOperator");
424             }
425         }
426
427         exprOp.generateExpression(acb, mb);
428     }
429
430     /** @see RelationalOperator#selfComparison
431      *
432      * @exception StandardException Thrown on error
433      */

434     public boolean selfComparison(ColumnReference cr)
435         throws StandardException
436     {
437         ValueNode otherSide;
438         JBitSet tablesReferenced;
439
440         /*
441         ** Figure out which side the given ColumnReference is on,
442         ** and look for the same table on the other side.
443         */

444         if (leftOperand == cr)
445         {
446             otherSide = rightOperand;
447         }
448         else if (rightOperand == cr)
449         {
450             otherSide = leftOperand;
451         }
452         else
453         {
454             otherSide = null;
455             if (SanityManager.DEBUG)
456             {
457                 SanityManager.THROWASSERT(
458                     "ColumnReference not found on either side of binary comparison.");
459             }
460         }
461
462         tablesReferenced = otherSide.getTablesReferenced();
463
464         /* Return true if the table we're looking for is in the bit map */
465         return tablesReferenced.get(cr.getTableNumber());
466     }
467
468     /** @see RelationalOperator#usefulStartKey */
469     public boolean usefulStartKey(Optimizable optTable)
470     {
471         /*
472         ** Determine whether this operator is a useful start operator
473         ** with knowledge of whether the key column is on the left or right.
474         */

475         int columnSide = columnOnOneSide(optTable);
476
477         if (columnSide == NEITHER)
478             return false;
479         else
480             return usefulStartKey(columnSide == LEFT);
481     }
482
483     /**
484      * Return true if a key column for the given table is found on the
485      * left side of this operator, false if it is found on the right
486      * side of this operator.
487      *
488      * NOTE: This method assumes that a key column will be found on one
489      * side or the other. If you don't know whether a key column exists,
490      * use the columnOnOneSide() method (below).
491      *
492      * @param optTable The Optimizable table that we're looking for a key
493      * column on.
494      *
495      * @return true if a key column for the given table is on the left
496      * side of this operator, false if one is found on the right
497      * side of this operator.
498      */

499     protected boolean keyColumnOnLeft(Optimizable optTable)
500     {
501         ColumnReference cr;
502         boolean left = false;
503
504         /* Is the key column on the left or the right? */
505         if (leftOperand instanceof ColumnReference)
506         {
507             /*
508             ** The left operand is a column reference.
509             ** Is it the correct column?
510             */

511             cr = (ColumnReference) leftOperand;
512             if (valNodeReferencesOptTable(
513                 cr, (FromTable)optTable, false, true))
514             {
515                 /* The left operand is the key column */
516                 left = true;
517             }
518         }
519
520         // Else the right operand must be the key column.
521
if (SanityManager.DEBUG)
522         {
523             if (!left)
524             {
525                 SanityManager.ASSERT(
526                     (rightOperand instanceof ColumnReference) &&
527                     valNodeReferencesOptTable((ColumnReference)rightOperand,
528                         (FromTable)optTable, false, true),
529                     "Key column not found on either side.");
530             }
531         }
532
533         return left;
534     }
535
536     /* Return values for columnOnOneSide */
537     protected static final int LEFT = -1;
538     protected static final int NEITHER = 0;
539     protected static final int RIGHT = 1;
540
541     /**
542      * Determine whether there is a column from the given table on one side
543      * of this operator, and if so, which side is it on?
544      *
545      * @param optTable The Optimizable table that we're looking for a key
546      * column on.
547      *
548      * @return LEFT if there is a column on the left, RIGHT if there is
549      * a column on the right, NEITHER if no column found on either
550      * side.
551      */

552     protected int columnOnOneSide(Optimizable optTable)
553     {
554         ColumnReference cr;
555         boolean left = false;
556         boolean walkSubtree = true;
557
558         /* Is a column on the left */
559         if (leftOperand instanceof ColumnReference)
560         {
561             /*
562             ** The left operand is a column reference.
563             ** Is it the correct column?
564             */

565             cr = (ColumnReference) leftOperand;
566             if (valNodeReferencesOptTable(
567                 cr, (FromTable)optTable, false, walkSubtree))
568             {
569                 /* Key column found on left */
570                 return LEFT;
571             }
572             walkSubtree = false;
573         }
574
575         if (rightOperand instanceof ColumnReference)
576         {
577             /*
578             ** The right operand is a column reference.
579             ** Is it the correct column?
580             */

581             cr = (ColumnReference) rightOperand;
582             if (valNodeReferencesOptTable(
583                 cr, (FromTable)optTable, false, walkSubtree))
584             {
585                 /* Key column found on right */
586                 return RIGHT;
587             }
588         }
589
590         return NEITHER;
591     }
592
593     /** @see RelationalOperator#usefulStopKey */
594     public boolean usefulStopKey(Optimizable optTable)
595     {
596         /*
597         ** Determine whether this operator is a useful start operator
598         ** with knowledge of whether the key column is on the left or right.
599         */

600         int columnSide = columnOnOneSide(optTable);
601
602         if (columnSide == NEITHER)
603             return false;
604         else
605             return usefulStopKey(columnSide == LEFT);
606     }
607
608     /**
609      * Determine whether this comparison operator is a useful stop key
610      * with knowledge of whether the key column is on the left or right.
611      *
612      * @param left true means the key column is on the left, false means
613      * it is on the right.
614      *
615      * @return true if this is a useful stop key
616      */

617     /** @see RelationalOperator#generateAbsoluteColumnId */
618     public void generateAbsoluteColumnId(MethodBuilder mb,
619                                                Optimizable optTable)
620     {
621         // Get the absolute column position for the column
622
int columnPosition = getAbsoluteColumnPosition(optTable);
623
624         mb.push(columnPosition);
625     }
626
627     /** @see RelationalOperator#generateRelativeColumnId */
628     public void generateRelativeColumnId(MethodBuilder mb,
629                                                Optimizable optTable)
630     {
631         // Get the absolute column position for the column
632
int columnPosition = getAbsoluteColumnPosition(optTable);
633         // Convert the absolute to the relative 0-based column position
634
columnPosition = optTable.convertAbsoluteToRelativeColumnPosition(
635                                 columnPosition);
636
637         mb.push(columnPosition);
638     }
639
640     /**
641      * Get the absolute 0-based column position of the ColumnReference from
642      * the conglomerate for this Optimizable.
643      *
644      * @param optTable The Optimizable
645      *
646      * @return The absolute 0-based column position of the ColumnReference
647      */

648     private int getAbsoluteColumnPosition(Optimizable optTable)
649     {
650         ColumnReference cr;
651         ConglomerateDescriptor bestCD;
652         int columnPosition;
653
654         if (keyColumnOnLeft(optTable))
655         {
656             cr = (ColumnReference) leftOperand;
657         }
658         else
659         {
660             cr = (ColumnReference) rightOperand;
661         }
662
663         bestCD = optTable.getTrulyTheBestAccessPath().
664                                                 getConglomerateDescriptor();
665
666         /*
667         ** Column positions are one-based, store is zero-based.
668         */

669         columnPosition = cr.getSource().getColumnPosition();
670
671         /*
672         ** If it's an index, find the base column position in the index
673         ** and translate it to an index column position.
674         */

675         if (bestCD != null && bestCD.isIndex())
676         {
677             columnPosition = bestCD.getIndexDescriptor().
678               getKeyColumnPosition(columnPosition);
679
680             if (SanityManager.DEBUG)
681             {
682                 SanityManager.ASSERT(columnPosition > 0,
683                     "Base column not found in index");
684             }
685         }
686
687         // return the 0-based column position
688
return columnPosition - 1;
689     }
690
691     /**
692      * @exception StandardException Thrown on error
693      */

694     public void generateQualMethod(ExpressionClassBuilder acb,
695                                    MethodBuilder mb,
696                                    Optimizable optTable)
697                         throws StandardException
698     {
699         /* Generate a method that returns the expression */
700         MethodBuilder qualMethod = acb.newUserExprFun();
701
702         /*
703         ** Generate the expression that's on the opposite side
704         ** of the key column
705         */

706         if (keyColumnOnLeft(optTable))
707         {
708             rightOperand.generateExpression(acb, qualMethod);
709         }
710         else
711         {
712             leftOperand.generateExpression(acb, qualMethod);
713         }
714
715         qualMethod.methodReturn();
716         qualMethod.complete();
717
718         /* push an expression that evaluates to the GeneratedMethod */
719         acb.pushMethodReference(mb, qualMethod);
720     }
721
722     /** @see RelationalOperator#generateOrderedNulls */
723     public void generateOrderedNulls(MethodBuilder mb)
724     {
725         mb.push(false);
726     }
727
728     /** @see RelationalOperator#orderedNulls */
729     public boolean orderedNulls()
730     {
731         return false;
732     }
733
734     /** @see RelationalOperator#isQualifier
735      *
736      * @exception StandardException Thrown on error
737      */

738     public boolean isQualifier(Optimizable optTable, boolean forPush)
739         throws StandardException
740     {
741         FromTable ft;
742         ValueNode otherSide = null;
743         JBitSet tablesReferenced;
744         ColumnReference cr = null;
745         boolean found = false;
746         boolean walkSubtree = true;
747
748         ft = (FromTable) optTable;
749
750         if (leftOperand instanceof ColumnReference)
751         {
752             /*
753             ** The left operand is a column reference.
754             ** Is it the correct column?
755             */

756             cr = (ColumnReference) leftOperand;
757             if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree))
758             {
759                 otherSide = rightOperand;
760                 found = true;
761             }
762             walkSubtree = false;
763         }
764
765         if ( ( ! found) && (rightOperand instanceof ColumnReference) )
766         {
767             /*
768             ** The right operand is a column reference.
769             ** Is it the correct column?
770             */

771             cr = (ColumnReference) rightOperand;
772             if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree))
773             {
774                 otherSide = leftOperand;
775                 found = true;
776             }
777         }
778
779         /* Have we found a ColumnReference on either side? */
780         if ( ! found)
781         {
782             /*
783             ** Neither side is a ColumnReference to the table we're looking
784             ** for, so it can't be a Qualifier
785             */

786             return false;
787         }
788
789         /*
790         ** One side is a ColumnReference to the correct table. It is a
791         ** Qualifier if the other side does not refer to the table we are
792         ** optimizing.
793         */

794         return !valNodeReferencesOptTable(otherSide, ft, forPush, true);
795     }
796
797     /**
798      * @see RelationalOperator#getOrderableVariantType
799      *
800      * @exception StandardException thrown on error
801      */

802     public int getOrderableVariantType(Optimizable optTable)
803         throws StandardException
804     {
805         /* The Qualifier's orderable is on the opposite side from
806          * the key column.
807          */

808         if (keyColumnOnLeft(optTable))
809         {
810             return rightOperand.getOrderableVariantType();
811         }
812         else
813         {
814             return leftOperand.getOrderableVariantType();
815         }
816     }
817
818     /** @see RelationalOperator#compareWithKnownConstant */
819     public boolean compareWithKnownConstant(Optimizable optTable, boolean considerParameters)
820     {
821         ValueNode node = null;
822         node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand;
823
824         if (considerParameters)
825         {
826             return (node instanceof ConstantNode) ||
827                         ((node.requiresTypeFromContext()) &&
828                          (((ParameterNode)node).getDefaultValue() != null));
829         }
830         else
831         {
832             return node instanceof ConstantNode;
833         }
834     }
835
836     /**
837      * @see RelationalOperator#getCompareValue
838      *
839      * @exception StandardException Thrown on error
840      */

841     public DataValueDescriptor getCompareValue(Optimizable optTable)
842         throws StandardException
843     {
844         ValueNode node = null;
845
846         /* The value being compared to is on the opposite side from
847         ** the key column.
848         */

849         node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand;
850
851         if (node instanceof ConstantNode)
852         {
853             return ((ConstantNode)node).getValue();
854         }
855         else if (node.requiresTypeFromContext())
856         {
857             ParameterNode pn;
858             if (node instanceof UnaryOperatorNode)
859                 pn = ((UnaryOperatorNode)node).getParameterOperand();
860             else
861                 pn = (ParameterNode) (node);
862             return pn.getDefaultValue();
863         }
864         else
865         {
866             return null;
867         }
868     }
869
870
871     /**
872      * Return 50% if this is a comparison with a boolean column, a negative
873      * selectivity otherwise.
874      */

875     protected double booleanSelectivity(Optimizable optTable)
876     throws StandardException
877     {
878         TypeId typeId = null;
879         double retval = -1.0d;
880         int columnSide;
881
882         columnSide = columnOnOneSide(optTable);
883
884         if (columnSide == LEFT)
885             typeId = leftOperand.getTypeId();
886         else if (columnSide == RIGHT)
887             typeId = rightOperand.getTypeId();
888
889         if (typeId != null && (typeId.getJDBCTypeId() == Types.BIT ||
890         typeId.getJDBCTypeId() == JDBC30Translation.SQL_TYPES_BOOLEAN))
891             retval = 0.5d;
892
893         return retval;
894     }
895
896     /**
897      * The methods generated for this node all are on Orderable.
898      * Overrides this method
899      * in BooleanOperatorNode for code generation purposes.
900      */

901     public String JavaDoc getReceiverInterfaceName() {
902         return ClassName.DataValueDescriptor;
903     }
904     
905     /**
906      * Returns the negation of this operator; negation of Equals is NotEquals.
907      */

908     BinaryOperatorNode getNegation(ValueNode leftOperand,
909                                           ValueNode rightOperand)
910         throws StandardException
911     {
912         BinaryOperatorNode negation;
913         if (SanityManager.DEBUG)
914             SanityManager.ASSERT(dataTypeServices != null,
915                                  "dataTypeServices is expected to be non-null");
916         /* xxxRESOLVE: look into doing this in place instead of allocating a new node */
917         negation = (BinaryOperatorNode)
918             getNodeFactory().getNode(getNegationNode(),
919                                      leftOperand, rightOperand,
920                                      getContextManager());
921         negation.setType(dataTypeServices);
922         return negation;
923     }
924
925     /* map current node to its negation */
926     private int getNegationNode()
927     {
928         switch (getNodeType())
929         {
930             case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE:
931                 return C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE;
932
933             case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE:
934                 return C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE;
935
936             case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE:
937                 return C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE;
938
939             case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE:
940                 return C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE;
941                 
942             case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE:
943                 return C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE;
944
945             case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE:
946                 return C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE;
947         }
948         
949         if (SanityManager.DEBUG)
950         {
951             SanityManager.THROWASSERT("getNegationNode called with invalid nodeType: " + getNodeType());
952         }
953
954         return -1;
955     }
956     
957     /**
958      * is this is useful start key? for example a predicate of the from
959      * <em>column Lessthan 5</em> is not a useful start key but is a useful stop
960      * key. However <em>5 Lessthan column </em> is a useful start key.
961      *
962      * @param columnOnLeft is true if the column is the left hand side of the
963      * binary operator.
964      */

965     protected boolean usefulStartKey(boolean columnOnLeft)
966     {
967         switch (operatorType)
968         {
969             case RelationalOperator.EQUALS_RELOP:
970                 return true;
971             case RelationalOperator.NOT_EQUALS_RELOP:
972                 return false;
973             case RelationalOperator.GREATER_THAN_RELOP:
974             case RelationalOperator.GREATER_EQUALS_RELOP:
975                 // col > 1
976
return columnOnLeft;
977             case RelationalOperator.LESS_THAN_RELOP:
978             case RelationalOperator.LESS_EQUALS_RELOP:
979                 // col < 1
980
return !columnOnLeft;
981             default:
982                 return false;
983         }
984
985
986     }
987
988     /** @see RelationalOperator#usefulStopKey */
989     protected boolean usefulStopKey(boolean columnOnLeft)
990     {
991         switch (operatorType)
992         {
993             case RelationalOperator.EQUALS_RELOP:
994                 return true;
995             case RelationalOperator.NOT_EQUALS_RELOP:
996                 return false;
997             case RelationalOperator.GREATER_THAN_RELOP:
998             case RelationalOperator.GREATER_EQUALS_RELOP:
999                 // col > 1
1000
return !columnOnLeft;
1001            case RelationalOperator.LESS_EQUALS_RELOP:
1002            case RelationalOperator.LESS_THAN_RELOP:
1003                // col < 1
1004
return columnOnLeft;
1005            default:
1006                return false;
1007        }
1008    }
1009    
1010    /** @see RelationalOperator#getStartOperator */
1011    public int getStartOperator(Optimizable optTable)
1012    {
1013        switch (operatorType)
1014        {
1015            case RelationalOperator.EQUALS_RELOP:
1016            case RelationalOperator.LESS_EQUALS_RELOP:
1017            case RelationalOperator.GREATER_EQUALS_RELOP:
1018                return ScanController.GE;
1019            case RelationalOperator.LESS_THAN_RELOP:
1020            case RelationalOperator.GREATER_THAN_RELOP:
1021                return ScanController.GT;
1022            case RelationalOperator.NOT_EQUALS_RELOP:
1023                if (SanityManager.DEBUG)
1024                    SanityManager.THROWASSERT("!= cannot be a start operator");
1025                return ScanController.NA;
1026            default:
1027                return ScanController.NA;
1028
1029        }
1030    }
1031    
1032    /** @see RelationalOperator#getStopOperator */
1033    public int getStopOperator(Optimizable optTable)
1034    {
1035        switch (operatorType)
1036        {
1037            case RelationalOperator.EQUALS_RELOP:
1038            case RelationalOperator.GREATER_EQUALS_RELOP:
1039            case RelationalOperator.LESS_EQUALS_RELOP:
1040                return ScanController.GT;
1041            case RelationalOperator.LESS_THAN_RELOP:
1042            case RelationalOperator.GREATER_THAN_RELOP:
1043                return ScanController.GE;
1044            case RelationalOperator.NOT_EQUALS_RELOP:
1045                if (SanityManager.DEBUG)
1046                    SanityManager.THROWASSERT("!= cannot be a stop operator");
1047                return ScanController.NA;
1048            default:
1049                return ScanController.NA;
1050        }
1051    }
1052
1053    /** @see RelationalOperator#generateOperator */
1054    public void generateOperator(MethodBuilder mb,
1055                                 Optimizable optTable)
1056    {
1057        switch (operatorType)
1058        {
1059            case RelationalOperator.EQUALS_RELOP:
1060                mb.push(Orderable.ORDER_OP_EQUALS);
1061                break;
1062
1063            case RelationalOperator.NOT_EQUALS_RELOP:
1064                mb.push(Orderable.ORDER_OP_EQUALS);
1065                break;
1066
1067            case RelationalOperator.LESS_THAN_RELOP:
1068            case RelationalOperator.GREATER_EQUALS_RELOP:
1069                mb.push(keyColumnOnLeft(optTable) ?
1070                        Orderable.ORDER_OP_LESSTHAN : Orderable.ORDER_OP_LESSOREQUALS);
1071                break;
1072            case RelationalOperator.LESS_EQUALS_RELOP:
1073            case RelationalOperator.GREATER_THAN_RELOP:
1074                mb.push(keyColumnOnLeft(optTable) ?
1075                        Orderable.ORDER_OP_LESSOREQUALS : Orderable.ORDER_OP_LESSTHAN);
1076                
1077        }
1078    }
1079    
1080    /** @see RelationalOperator#generateNegate */
1081    public void generateNegate(MethodBuilder mb, Optimizable optTable)
1082    {
1083        switch (operatorType)
1084        {
1085            case RelationalOperator.EQUALS_RELOP:
1086                mb.push(false);
1087                break;
1088            case RelationalOperator.NOT_EQUALS_RELOP:
1089                mb.push(true);
1090                break;
1091            case RelationalOperator.LESS_THAN_RELOP:
1092            case RelationalOperator.LESS_EQUALS_RELOP:
1093                mb.push(!keyColumnOnLeft(optTable));
1094                break;
1095            case RelationalOperator.GREATER_THAN_RELOP:
1096            case RelationalOperator.GREATER_EQUALS_RELOP:
1097                mb.push(keyColumnOnLeft(optTable));
1098                break;
1099        }
1100        
1101        return;
1102    }
1103        
1104    /** @see RelationalOperator#getOperator */
1105    public int getOperator()
1106    {
1107        return operatorType;
1108    }
1109
1110    /** return the selectivity of this predicate.
1111     */

1112    public double selectivity(Optimizable optTable)
1113    throws StandardException
1114    {
1115        double retval = booleanSelectivity(optTable);
1116        
1117        if (retval >= 0.0d)
1118            return retval;
1119            
1120        switch (operatorType)
1121        {
1122            case RelationalOperator.EQUALS_RELOP:
1123                return 0.1;
1124            case RelationalOperator.NOT_EQUALS_RELOP:
1125            case RelationalOperator.LESS_THAN_RELOP:
1126            case RelationalOperator.LESS_EQUALS_RELOP:
1127            case RelationalOperator.GREATER_EQUALS_RELOP:
1128                if (getBetweenSelectivity())
1129                    return 0.5d;
1130                /* fallthrough -- only */
1131            case RelationalOperator.GREATER_THAN_RELOP:
1132                return 0.33;
1133        }
1134        
1135        return 0.0;
1136    }
1137
1138    /** @see RelationalOperator#getTransitiveSearchClause */
1139    public RelationalOperator getTransitiveSearchClause(ColumnReference otherCR)
1140        throws StandardException
1141    {
1142        return (RelationalOperator)getNodeFactory().getNode(getNodeType(),
1143                                                          otherCR,
1144                                                          rightOperand,
1145                                                          getContextManager());
1146    }
1147    
1148    public boolean equalsComparisonWithConstantExpression(Optimizable optTable)
1149    {
1150        if (operatorType != EQUALS_RELOP)
1151            return false;
1152
1153        boolean retval = false;
1154        ValueNode comparand = null;
1155
1156        int side = columnOnOneSide(optTable);
1157        if (side == LEFT)
1158        {
1159            retval = rightOperand.isConstantExpression();
1160        }
1161        else if (side == RIGHT)
1162        {
1163            retval = leftOperand.isConstantExpression();
1164        }
1165
1166        return retval;
1167    }
1168    
1169    /** @see ValueNode#isRelationalOperator */
1170    public boolean isRelationalOperator()
1171    {
1172        return true;
1173    }
1174    
1175    public boolean isBinaryEqualsOperatorNode()
1176    {
1177        return (operatorType == RelationalOperator.EQUALS_RELOP);
1178    }
1179
1180    /** @see ValueNode#optimizableEqualityNode */
1181    public boolean optimizableEqualityNode(Optimizable optTable,
1182                                           int columnNumber,
1183                                           boolean isNullOkay)
1184        throws StandardException
1185    {
1186        if (operatorType != EQUALS_RELOP)
1187            return false;
1188
1189        ColumnReference cr = getColumnOperand(optTable,
1190                                              columnNumber);
1191        if (cr == null)
1192            return false;
1193
1194        if (selfComparison(cr))
1195            return false;
1196        
1197        if (implicitVarcharComparison())
1198            return false;
1199        
1200        return true;
1201    }
1202    
1203    /**
1204     * Return whether or not this binary relational predicate requires an implicit
1205     * (var)char conversion. This is important when considering
1206     * hash join since this type of equality predicate is not currently
1207     * supported for a hash join.
1208     *
1209     * @return Whether or not an implicit (var)char conversion is required for
1210     * this binary relational operator.
1211     *
1212     * @exception StandardException Thrown on error
1213     */

1214
1215    private boolean implicitVarcharComparison()
1216        throws StandardException
1217    {
1218        TypeId leftType = leftOperand.getTypeId();
1219        TypeId rightType = rightOperand.getTypeId();
1220        
1221        if (leftType.isStringTypeId() && !rightType.isStringTypeId())
1222            return true;
1223
1224        if (rightType.isStringTypeId() && (!leftType.isStringTypeId()))
1225            return true;
1226
1227        return false;
1228    }
1229    
1230    /* @see BinaryOperatorNode#genSQLJavaSQLTree
1231     * @see BinaryComparisonOperatorNode#genSQLJavaSQLTree
1232     */

1233    public ValueNode genSQLJavaSQLTree() throws StandardException
1234    {
1235        if (operatorType == EQUALS_RELOP)
1236            return this;
1237        
1238        return super.genSQLJavaSQLTree();
1239    }
1240
1241    /**
1242     * Take a ResultSetNode and return a column reference that is scoped for
1243     * for the received ResultSetNode, where "scoped" means that the column
1244     * reference points to a specific column in the RSN. This is used for
1245     * remapping predicates from an outer query down to a subquery.
1246     *
1247     * For example, assume we have the following query:
1248     *
1249     * select * from
1250     * (select i,j from t1 union select i,j from t2) X1,
1251     * (select a,b from t3 union select a,b from t4) X2
1252     * where X1.j = X2.b;
1253     *
1254     * Then assume that this BinaryRelationalOperatorNode represents the
1255     * "X1.j = X2.b" predicate and that the childRSN we received as a
1256     * parameter represents one of the subqueries to which we want to push
1257     * the predicate; let's say it's:
1258     *
1259     * select i,j from t1
1260     *
1261     * Then what we want to do in this method is map one of the operands
1262     * X1.j or X2.b (depending on the 'whichSide' parameter) to the childRSN,
1263     * if possible. Note that in our example, "X2.b" should _NOT_ be mapped
1264     * because it doesn't apply to the childRSN for the subquery "select i,j
1265     * from t1"; thus we should leave it as it is. "X1.j", however, _does_
1266     * need to be scoped, and so this method will return a ColumnReference
1267     * pointing to "T1.j" (or whatever the corresponding column in T1 is).
1268     *
1269     * ASSUMPTION: We should only get to this method if we know that
1270     * exactly one operand in the predicate to which this operator belongs
1271     * can and should be mapped to the received childRSN.
1272     *
1273     * @param whichSide The operand are we trying to scope (LEFT or RIGHT)
1274     * @param parentRSNsTables Set of all table numbers referenced by
1275     * the ResultSetNode that is _parent_ to the received childRSN.
1276     * We need this to make sure we don't scope the operand to a
1277     * ResultSetNode to which it doesn't apply.
1278     * @param childRSN The result set node to which we want to create
1279     * a scoped predicate.
1280     * @param whichRC If not -1 then this tells us which ResultColumn
1281     * in the received childRSN we need to use for the scoped predicate;
1282     * if -1 then the column position of the scoped column reference
1283     * will be stored in this array and passed back to the caller.
1284     * @return A column reference scoped to the received childRSN, if possible.
1285     * If the operand is a ColumnReference that is not supposed to be scoped,
1286     * we return a _clone_ of the reference--this is necessary because the
1287     * reference is going to be pushed to two places (left and right children
1288     * of the parentRSN) and if both children are referencing the same
1289     * instance of the column reference, they'll interfere with each other
1290     * during optimization.
1291     */

1292    public ValueNode getScopedOperand(int whichSide,
1293        JBitSet parentRSNsTables, ResultSetNode childRSN,
1294        int [] whichRC) throws StandardException
1295    {
1296        ResultColumn rc = null;
1297        ColumnReference cr =
1298            whichSide == LEFT
1299                ? (ColumnReference)leftOperand
1300                : (ColumnReference)rightOperand;
1301
1302        /* When we scope a predicate we only scope one side of it--the
1303         * side that is to be evaluated against childRSN. We figure out
1304         * if "cr" is that side by using table numbers, as seen below.
1305         * This means that for every scoped predicate there will be one
1306         * operand that is scoped and one operand that is not scoped.
1307         * When we get here for the operand that will not be scoped,
1308         * we'll just return a clone of that operand. So in the example
1309         * mentioned above, the scoped predicate for the left child of
1310         * X1 would be
1311         *
1312         * T1.j <scoped> = X2.b <clone>
1313         *
1314         * That said, the first thing we need to do is see if this
1315         * ColumnReference is supposed to be scoped for childRSN. We
1316         * do that by figuring out what underlying base table the column
1317         * reference is pointing to and then seeing if that base table
1318         * is included in the list of table numbers from the parentRSN.
1319         */

1320        JBitSet crTables = new JBitSet(parentRSNsTables.size());
1321        BaseTableNumbersVisitor btnVis =
1322            new BaseTableNumbersVisitor(crTables);
1323        cr.accept(btnVis);
1324
1325        /* If the column reference in question is not intended for
1326         * the received result set node, just leave the operand as
1327         * it is (i.e. return a clone). In the example mentioned at
1328         * the start of this method, this will happen when the operand
1329         * is X2.b and childRSN is either "select i,j from t1" or
1330         * "select i,j from t2", in which case the operand does not
1331         * apply to childRSN. When we get here and try to map the
1332         * "X1.j" operand, though, the following "contains" check will
1333         * return true and thus we can go ahead and return a scoped
1334         * version of that operand.
1335         */

1336        if (!parentRSNsTables.contains(crTables))
1337            return (ColumnReference)cr.getClone();
1338
1339        /* Find the target ResultColumn in the received result set. At
1340         * this point we know that we do in fact need to scope the column
1341         * reference for childRSN, so go ahead and do it. The way in
1342         * which we get the scope target column differs depending on
1343         * if childRSN corresponds to the left or right child of the
1344         * UNION node. Before explaining that, though, note that it's
1345         * not good enough to just search for the target column by
1346         * name. The reason is that it's possible the name provided
1347         * for the column reference to be scoped doesn't match the
1348         * name of the actual underlying column. Ex.
1349         *
1350         * select * from
1351         * (select i,j from t1 union select i,j from t2) X1 (x,y),
1352         * (select a,b from t3 union select a,b from t4) X2
1353         * where X1.x = X2.b;
1354         *
1355         * If we were scoping "X1.x" and we searched for "x" in the
1356         * childRSN "select i,j from t1" we wouldn't find it.
1357         *
1358         * It is similarly incorrect to search for the target column
1359         * by position (DERBY-1633). This is a bit more subtle, but
1360         * if the child to which we're scoping is a subquery whose RCL
1361         * does not match the column ordering of the RCL for cr's source
1362         * result set, then searching by column position can yield the
1363         * wrong results, as well. For a detailed example of how this
1364         * can happen, see the fix description attached to DERBY-1633.
1365         *
1366         * So how do we find the target column, then? As mentioned
1367         * above, the way in which we get the scope target column
1368         * differs depending on if childRSN corresponds to the left
1369         * or right child of the parent UNION node. And that said,
1370         * we can tell if we're scoping a left child by looking at
1371         * "whichRC" argument: if it is -1 then we know we're scoping
1372         * to the left child of a Union; otherwise we're scoping to
1373         * the right child.
1374         */

1375        if (whichRC[0] == -1)
1376        {
1377            /*
1378             * For the left side we start by figuring out what the source
1379             * result set and column position for "cr" are. Then, since
1380             * a) cr must be pointing to a result column in the parentRSN's
1381             * ResultColumnList, b) we know that the parent RSN is a
1382             * SetOperatorNode (at least for now, since we only get here
1383             * for Union nodes), and c) SetOpNode's RCLs are built from the
1384             * left child's RCL (see bindResultColumns() in SetOperatorNode),
1385             * we know that if we search the child's RCL for a reference
1386             * whose source result column is the same as cr's source result
1387             * column, we'll find a match. Once found, the position of the
1388             * matching column w.r.t childRSN's RCL will be stored in the
1389             * whichRC parameter.
1390             */

1391
1392            // Find the source result set and source column position of cr.
1393
int [] sourceColPos = new int[] {-1};
1394            ResultSetNode sourceRSN = cr.getSourceResultSet(sourceColPos);
1395
1396            if (SanityManager.DEBUG)
1397            {
1398                /* We assumed that if we made it here "cr" was pointing
1399                 * to a base table somewhere down the tree. If that's
1400                 * true then sourceRSN won't be null. Make sure our
1401                 * assumption was correct.
1402                 */

1403                SanityManager.ASSERT(sourceRSN != null,
1404                    "Failed to find source result set when trying to " +
1405                    "scope column reference '" + cr.getTableName() +
1406                    "." + cr.getColumnName());
1407            }
1408
1409            // Now search for the corresponding ResultColumn in childRSN.
1410
rc = childRSN.getResultColumns()
1411                    .getResultColumn(sourceColPos[0], sourceRSN, whichRC);
1412        }
1413        else
1414        {
1415            /*
1416             * For the right side the story is slightly different. If we were
1417             * to search the right child's RCL for a reference whose source
1418             * result column was the same as cr's, we wouldn't find it. This
1419             * is because cr's source result column comes from the left child's
1420             * RCL and thus the right child doesn't know about it. That said,
1421             * though, for set operations like UNION, the left and right RCL's
1422             * are correlated by position--i.e. the operation occurs between
1423             * the nth column in the left RCL and the nth column in the right
1424             * RCL. So given that we will already have found the scope target
1425             * in the left child's RCL at the position in whichRC, we know that
1426             * that scope target for the right child's RCL is simply the
1427             * whichRC'th column in that RCL.
1428             */

1429            rc = childRSN.getResultColumns().getResultColumn(whichRC[0]);
1430        }
1431
1432        // rc shouldn't be null; if there was no matching ResultColumn at all,
1433
// then we shouldn't have made it this far.
1434
if (SanityManager.DEBUG)
1435        {
1436            SanityManager.ASSERT(rc != null,
1437                "Failed to locate scope target result column when trying to " +
1438                "scope operand '" + cr.getTableName() + "." +
1439                cr.getColumnName() + "'.");
1440        }
1441
1442        /* If the ResultColumn we found has an expression that is a
1443         * ColumnReference, then that column reference has all of the
1444         * info we need.
1445         *
1446         * It is, however, possible that the ResultColumn's expression
1447         * is NOT a ColumnReference. For example, the expression would
1448         * be a constant expression if childRSN represented something
1449         * like:
1450         *
1451         * select 1, 1 from t1
1452         *
1453         * In this case the expression does not directly reference a
1454         * column in the underlying result set and is therefore
1455         * "scoped" as far as it can go. This means that the scoped
1456         * predicate will not necessarily have column references on
1457         * both sides, even though the predicate that we're scoping
1458         * will. That's not a problem, though, since a predicate with
1459         * a column reference on one side and a non-ColumnReference
1460         * on the other is still valid.
1461         */

1462
1463        if (rc.getExpression() instanceof ColumnReference)
1464        {
1465            /* We create a clone of the column reference and mark
1466             * the clone as "scoped" so that we can do the right
1467             * thing when it comes time to remap the predicate;
1468             * see Predicate.remapScopedPred() for more.
1469             */

1470            ColumnReference cRef = (ColumnReference)
1471                ((ColumnReference)rc.getExpression()).getClone();
1472            cRef.markAsScoped();
1473            return cRef;
1474        }
1475
1476        /* Else just return rc's expression. This means the scoped
1477         * predicate will have one operand that is _not_ a column
1478         * reference--but that's okay, so long as we account for
1479         * that when pushing/remapping the scoped predicate down
1480         * the query tree (see esp. "isScopedToSourceResultSet()"
1481         * in Predicate.java).
1482         */

1483        return rc.getExpression();
1484    }
1485
1486    /**
1487     * Determine whether or not the received ValueNode (which will
1488     * usually be a ColumnReference) references either the received
1489     * optTable or else a base table in the subtree beneath that
1490     * optTable.
1491     *
1492     * @param valNode The ValueNode that has the reference(s).
1493     * @param optTable The table/subtree node to which we're trying
1494     * to find a reference.
1495     * @param forPush Whether or not we are searching with the intent
1496     * to push this operator to the target table.
1497     * @param walkOptTableSubtree Should we walk the subtree beneath
1498     * optTable to find base tables, or not? Will be false if we've
1499     * already done it for the left operand and now we're here
1500     * for the right operand.
1501     * @return True if valNode contains a reference to optTable or
1502     * to a base table in the subtree beneath optTable; false
1503     * otherwise.
1504     */

1505    private boolean valNodeReferencesOptTable(ValueNode valNode,
1506        FromTable optTable, boolean forPush, boolean walkOptTableSubtree)
1507    {
1508        // Following call will initialize/reset the btnVis,
1509
// valNodeBaseTables, and optBaseTables fields of this object.
1510
initBaseTableVisitor(optTable.getReferencedTableMap().size(),
1511            walkOptTableSubtree);
1512
1513        boolean found = false;
1514        try {
1515
1516            // Find all base tables beneath optTable and load them
1517
// into this object's optBaseTables map. This is the
1518
// list of table numbers we'll search to see if the
1519
// value node references any tables in the subtree at
1520
// or beneath optTable.
1521
if (walkOptTableSubtree)
1522                buildTableNumList(optTable, forPush);
1523
1524            // Now get the base table numbers that are in valNode's
1525
// subtree. In most cases valNode will be a ColumnReference
1526
// and this will return a single base table number.
1527
btnVis.setTableMap(valNodeBaseTables);
1528            valNode.accept(btnVis);
1529
1530            // And finally, see if there's anything in common.
1531
valNodeBaseTables.and(optBaseTables);
1532            found = (valNodeBaseTables.getFirstSetBit() != -1);
1533
1534        } catch (StandardException se) {
1535            if (SanityManager.DEBUG)
1536            {
1537                SanityManager.THROWASSERT("Failed when trying to " +
1538                    "find base table numbers for reference check:\n" +
1539                    se.getMessage());
1540            }
1541        }
1542
1543        return found;
1544    }
1545
1546    /**
1547     * Initialize the fields used for retrieving base tables in
1548     * subtrees, which allows us to do a more extensive search
1549     * for table references. If the fields have already been
1550     * created, then just reset their values.
1551     *
1552     * @param numTablesInQuery Used for creating JBitSets that
1553     * can hold table numbers for the query.
1554     * @param initOptBaseTables Whether or not we should clear out
1555     * or initialize the optBaseTables bit set.
1556     */

1557    private void initBaseTableVisitor(int numTablesInQuery,
1558        boolean initOptBaseTables)
1559    {
1560        if (valNodeBaseTables == null)
1561            valNodeBaseTables = new JBitSet(numTablesInQuery);
1562        else
1563            valNodeBaseTables.clearAll();
1564
1565        if (initOptBaseTables)
1566        {
1567            if (optBaseTables == null)
1568                optBaseTables = new JBitSet(numTablesInQuery);
1569            else
1570                optBaseTables.clearAll();
1571        }
1572
1573        // Now create the visitor. We give it valNodeBaseTables
1574
// here for sake of creation, but this can be overridden
1575
// (namely, by optBaseTables) by the caller of this method.
1576
if (btnVis == null)
1577            btnVis = new BaseTableNumbersVisitor(valNodeBaseTables);
1578    }
1579
1580    /**
1581     * Create a set of table numbers to search when trying to find
1582     * which (if either) of this operator's operands reference the
1583     * received target table. At the minimum this set should contain
1584     * the target table's own table number. After that, if we're
1585     * _not_ attempting to push this operator (or more specifically,
1586     * the predicate to which this operator belongs) to the target
1587     * table, we go on to search the subtree beneath the target
1588     * table and add any base table numbers to the searchable list.
1589     *
1590     * @param ft Target table for which we're building the search
1591     * list.
1592     * @param forPush Whether or not we are searching with the intent
1593     * to push this operator to the target table.
1594     */

1595    private void buildTableNumList(FromTable ft, boolean forPush)
1596        throws StandardException
1597    {
1598        // Start with the target table's own table number. Note
1599
// that if ft is an instanceof SingleChildResultSet, its
1600
// table number could be negative.
1601
if (ft.getTableNumber() >= 0)
1602            optBaseTables.set(ft.getTableNumber());
1603
1604        if (forPush)
1605        // nothing else to do.
1606
return;
1607
1608        // Add any table numbers from the target table's
1609
// reference map.
1610
optBaseTables.or(ft.getReferencedTableMap());
1611
1612        // The table's reference map is not guaranteed to have
1613
// all of the tables that are actually used--for example,
1614
// if the table is a ProjectRestrictNode or a JoinNode
1615
// with a subquery as a child, the ref map will contain
1616
// the number for the PRN above the subquery, but it
1617
// won't contain the table numbers referenced by the
1618
// subquery. So here we go through and find ALL base
1619
// table numbers beneath the target node.
1620
btnVis.setTableMap(optBaseTables);
1621        ft.accept(btnVis);
1622        return;
1623    }
1624
1625}
1626
Popular Tags