1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 25 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 26 27 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 28 import org.apache.derby.iapi.sql.compile.Visitable; 29 import org.apache.derby.iapi.sql.compile.Visitor; 30 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 31 import org.apache.derby.iapi.sql.compile.Optimizable; 32 33 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 34 35 import org.apache.derby.iapi.store.access.ScanController; 36 37 import org.apache.derby.iapi.error.StandardException; 38 39 import org.apache.derby.iapi.services.compiler.MethodBuilder; 40 41 import org.apache.derby.iapi.services.sanity.SanityManager; 42 43 import org.apache.derby.iapi.types.DataValueDescriptor; 44 45 import org.apache.derby.iapi.util.JBitSet; 46 47 import java.util.ArrayList ; 48 import java.util.Hashtable ; 49 50 55 56 public final class Predicate extends QueryTreeNode implements OptimizablePredicate, 57 Comparable 58 { 59 60 AndNode andNode; 61 boolean pushable; 62 63 JBitSet referencedSet; 64 67 int equivalenceClass = -1; 68 int indexPosition; 69 protected boolean startKey; 70 protected boolean stopKey; 71 protected boolean isQualifier; 72 73 76 private Hashtable searchClauseHT; 77 78 private boolean scoped; 81 82 88 89 public void init(Object andNode, Object referencedSet) 90 { 91 this.andNode = (AndNode) andNode; 92 pushable = false; 93 this.referencedSet = (JBitSet) referencedSet; 94 scoped = false; 95 } 96 97 100 101 104 public JBitSet getReferencedMap() 105 { 106 return referencedSet; 107 } 108 109 112 public boolean hasSubquery() 113 { 114 118 return ! pushable; 119 } 120 121 124 public boolean hasMethodCall() 125 { 126 130 return ! pushable; 131 } 132 133 134 public void markStartKey() 135 { 136 startKey = true; 137 } 138 139 140 public boolean isStartKey() 141 { 142 return startKey; 143 } 144 145 146 public void markStopKey() 147 { 148 stopKey = true; 149 } 150 151 152 public boolean isStopKey() 153 { 154 return stopKey; 155 } 156 157 158 public void markQualifier() 159 { 160 isQualifier = true; 161 } 162 163 164 public boolean isQualifier() 165 { 166 return isQualifier; 167 } 168 169 170 public boolean compareWithKnownConstant(Optimizable optTable, boolean considerParameters) 171 { 172 boolean retval = false; 173 RelationalOperator relop = getRelop(); 174 175 178 if (relop == null) 179 return false; 180 181 if (relop.compareWithKnownConstant(optTable, considerParameters)) 182 retval = true; 183 184 return retval; 185 } 186 187 public int hasEqualOnColumnList(int[] baseColumnPositions, 188 Optimizable optTable) 189 throws StandardException 190 { 191 RelationalOperator relop = getRelop(); 192 193 if (relop == null) 194 return -1; 195 196 if (!(relop.getOperator() == RelationalOperator.EQUALS_RELOP)) 197 return -1; 198 199 for (int i = 0; i < baseColumnPositions.length; i++) 200 { 201 ColumnReference cr = relop.getColumnOperand(optTable, 202 baseColumnPositions[i]); 203 204 if (cr == null) 205 continue; 206 207 if (relop.selfComparison(cr)) 208 continue; 209 210 return i; 213 } 214 215 return -1; 216 } 217 218 223 public DataValueDescriptor getCompareValue(Optimizable optTable) 224 throws StandardException 225 { 226 if (SanityManager.DEBUG) 227 { 228 SanityManager.ASSERT(compareWithKnownConstant(optTable, true), 229 "Cannot get the compare value if not comparing with a known constant."); 230 } 231 232 RelationalOperator relop = getRelop(); 233 234 return relop.getCompareValue(optTable); 235 } 236 237 238 public boolean equalsComparisonWithConstantExpression(Optimizable optTable) 239 { 240 RelationalOperator relop = getRelop(); 241 boolean retval = false; 242 243 if (relop != null) 244 { 245 retval = relop.equalsComparisonWithConstantExpression(optTable); 246 } 247 248 return retval; 249 } 250 251 252 public double selectivity(Optimizable optTable) 253 throws StandardException 254 { 255 return andNode.getLeftOperand().selectivity(optTable); 256 } 257 258 259 public int getIndexPosition() 260 { 261 return indexPosition; 262 } 263 264 265 266 267 public int compareTo(Object other) 268 { 269 Predicate otherPred = (Predicate) other; 270 271 296 297 int otherIndexPosition = otherPred.getIndexPosition(); 298 299 if (indexPosition < otherIndexPosition) 300 return -1; 301 302 if (indexPosition > otherIndexPosition) 303 return 1; 304 305 boolean thisIsEquals = false, otherIsEquals = false; 309 boolean thisIsNotEquals = true, otherIsNotEquals = true; 310 311 if (getRelop() != null) { 313 int thisOperator = ((RelationalOperator)andNode.getLeftOperand()).getOperator(); 314 thisIsEquals = (thisOperator == RelationalOperator.EQUALS_RELOP || 315 thisOperator == RelationalOperator.IS_NULL_RELOP); 316 thisIsNotEquals = (thisOperator == RelationalOperator.NOT_EQUALS_RELOP || 317 thisOperator == RelationalOperator.IS_NOT_NULL_RELOP); 318 } 319 if (otherPred.getRelop() != null) { 321 int otherOperator = ((RelationalOperator)(otherPred.getAndNode().getLeftOperand())).getOperator(); 322 otherIsEquals = (otherOperator == RelationalOperator.EQUALS_RELOP || 323 otherOperator == RelationalOperator.IS_NULL_RELOP); 324 otherIsNotEquals = (otherOperator == RelationalOperator.NOT_EQUALS_RELOP || 325 otherOperator == RelationalOperator.IS_NOT_NULL_RELOP); 326 } 327 328 boolean thisIsBefore = (thisIsEquals && ! otherIsEquals) || ( ! thisIsNotEquals && otherIsNotEquals); 329 if (thisIsBefore) 330 return -1; 331 332 boolean otherIsBefore = (otherIsEquals && ! thisIsEquals) || ( ! otherIsNotEquals && thisIsNotEquals); 333 if (otherIsBefore) 334 return 1; 335 return 0; 336 } 337 338 343 public AndNode getAndNode() 344 { 345 return andNode; 346 } 347 348 353 public void setAndNode(AndNode andNode) 354 { 355 this.andNode = andNode; 356 } 357 358 363 public boolean getPushable() 364 { 365 return pushable; 366 } 367 368 378 public void setPushable(boolean pushable) { 379 this.pushable = pushable; 380 } 381 382 387 public JBitSet getReferencedSet() 388 { 389 return referencedSet; 390 } 391 392 397 void setEquivalenceClass(int equivalenceClass) 398 { 399 this.equivalenceClass = equivalenceClass; 400 } 401 402 407 int getEquivalenceClass() 408 { 409 return equivalenceClass; 410 } 411 412 418 public void categorize() throws StandardException 419 { 420 pushable = andNode.categorize(referencedSet, false); 421 } 422 423 431 public RelationalOperator getRelop() 432 { 433 434 if (andNode.getLeftOperand() instanceof RelationalOperator) 435 { 436 return (RelationalOperator) andNode.getLeftOperand(); 437 } 438 else 439 { 440 return null; 441 } 442 } 443 444 public final boolean isOrList() 445 { 446 return(andNode.getLeftOperand() instanceof OrNode); 447 } 448 449 470 public final boolean isStoreQualifier() 471 { 472 if ((andNode.getLeftOperand() instanceof RelationalOperator) || 473 (andNode.getLeftOperand() instanceof OrNode)) 474 { 475 return(true); 476 } 477 else 478 { 479 return(false); 480 } 481 } 482 483 496 public final boolean isPushableOrClause(Optimizable optTable) 497 throws StandardException 498 { 499 boolean ret_val = true; 500 501 if (andNode.getLeftOperand() instanceof OrNode) 502 { 503 QueryTreeNode node = andNode.getLeftOperand(); 504 505 while (node instanceof OrNode) 506 { 507 OrNode or_node = (OrNode) node; 508 509 if (or_node.getLeftOperand() instanceof RelationalOperator) 510 { 511 if (!((RelationalOperator) or_node.getLeftOperand()). 514 isQualifier(optTable, true)) 515 { 516 return(false); 518 } 519 520 node = or_node.getRightOperand(); 521 } 522 else 523 { 524 526 return(false); 527 } 528 } 529 530 return(true); 531 } 532 else 533 { 534 return(false); 536 } 537 } 538 539 552 boolean transitiveSearchClauseAdded(RelationalOperator ro) 553 { 554 if (searchClauseHT == null || 555 searchClauseHT.get(new Integer (ro.getOperator())) == null) 556 { 557 return false; 558 } 559 else 560 { 561 return true; 562 } 563 } 564 565 573 void setTransitiveSearchClauseAdded(RelationalOperator ro) 574 { 575 if (searchClauseHT == null) 576 { 577 searchClauseHT = new Hashtable (); 578 } 579 582 Integer i = new Integer (ro.getOperator()); 583 searchClauseHT.put(i, i); 584 } 585 586 594 int getStartOperator(Optimizable optTable) 595 { 596 if (SanityManager.DEBUG) 597 { 598 SanityManager.ASSERT(startKey, "Getting a start operator from a Predicate that's not a start key."); 599 } 600 601 604 if (andNode.getLeftOperand() instanceof InListOperatorNode) 605 return ScanController.GE; 606 607 return getRelop().getStartOperator(optTable); 608 } 609 610 int getStopOperator(Optimizable optTable) 611 { 612 if (SanityManager.DEBUG) 613 { 614 SanityManager.ASSERT(stopKey, "Getting a stop operator from a Predicate that's not a stop key."); 615 } 616 617 620 if (andNode.getLeftOperand() instanceof InListOperatorNode) 621 return ScanController.GT; 622 623 return getRelop().getStopOperator(optTable); 624 } 625 626 632 void setIndexPosition(int indexPosition) 633 { 634 this.indexPosition = indexPosition; 635 } 636 637 640 void clearScanFlags() 641 { 642 startKey = false; 643 stopKey = false; 644 isQualifier = false; 645 } 646 647 650 void clearQualifierFlag() 651 { 652 isQualifier = false; 653 } 654 655 void generateExpressionOperand(Optimizable optTable, 656 int columnPosition, 657 ExpressionClassBuilder acb, 658 MethodBuilder mb) 659 throws StandardException 660 { 661 getRelop().generateExpressionOperand(optTable, 662 columnPosition, 663 acb, 664 mb); 665 } 666 667 void generateAbsoluteColumnId(MethodBuilder mb, 668 Optimizable optTable) 669 { 670 getRelop().generateAbsoluteColumnId(mb, optTable); 671 } 672 673 void generateRelativeColumnId(MethodBuilder mb, 674 Optimizable optTable) 675 { 676 getRelop().generateRelativeColumnId(mb, optTable); 677 } 678 679 void generateOperator(MethodBuilder mb, 680 Optimizable optTable) 681 { 682 getRelop().generateOperator(mb, optTable); 683 } 684 685 void generateQualMethod(ExpressionClassBuilder acb, 686 MethodBuilder mb, 687 Optimizable optTable) 688 throws StandardException 689 { 690 getRelop().generateQualMethod(acb, mb, optTable); 691 } 692 693 void generateOrderedNulls(MethodBuilder mb) 694 { 695 getRelop().generateOrderedNulls(mb); 696 } 697 698 void generateNegate(MethodBuilder mb, 699 Optimizable optTable) 700 { 701 getRelop().generateNegate(mb, optTable); 702 } 703 704 void generateOrderableVariantType(MethodBuilder mb, 705 Optimizable optTable) 706 throws StandardException 707 { 708 int variantType = getRelop().getOrderableVariantType(optTable); 709 mb.push(variantType); 710 711 } 712 718 719 public String toString() 720 { 721 if (SanityManager.DEBUG) 722 { 723 return binaryRelOpColRefsToString() + "\nreferencedSet: " + 724 referencedSet + "\n" + "pushable: " + pushable + "\n" + 725 super.toString(); 726 } 727 else 728 { 729 return ""; 730 } 731 } 732 733 742 public String binaryRelOpColRefsToString() 743 { 744 if (!(getAndNode().getLeftOperand() 746 instanceof BinaryRelationalOperatorNode)) 747 { 748 return ""; 749 } 750 751 final String DUMMY_VAL = "<expr>"; 752 java.lang.StringBuffer sBuf = new java.lang.StringBuffer (); 753 BinaryRelationalOperatorNode opNode = 754 (BinaryRelationalOperatorNode)getAndNode().getLeftOperand(); 755 756 if (opNode.getLeftOperand() instanceof ColumnReference) 758 { 759 sBuf.append( 760 ((ColumnReference)opNode.getLeftOperand()).getTableName() + 761 "." + 762 ((ColumnReference)opNode.getLeftOperand()).getColumnName() 763 ); 764 } 765 else 766 sBuf.append(DUMMY_VAL); 767 768 sBuf.append(" " + opNode.operator + " "); 770 771 if (opNode.getRightOperand() instanceof ColumnReference) { 773 sBuf.append( 774 ((ColumnReference)opNode.getRightOperand()).getTableName() + 775 "." + 776 ((ColumnReference)opNode.getRightOperand()).getColumnName() 777 ); 778 } 779 else 780 sBuf.append(DUMMY_VAL); 781 782 return sBuf.toString(); 783 } 784 785 791 792 public void printSubNodes(int depth) 793 { 794 if (SanityManager.DEBUG) 795 { 796 printLabel(depth, "andNode: "); 797 andNode.treePrint(depth + 1); 798 super.printSubNodes(depth); 799 } 800 } 801 802 810 public Visitable accept(Visitor v) 811 throws StandardException 812 { 813 if (v.skipChildren(this)) 814 { 815 return v.visit(this); 816 } 817 818 Visitable returnNode = super.accept(v); 819 820 if (andNode != null && !v.stopTraversal()) 821 { 822 andNode = (AndNode)andNode.accept(v); 823 } 824 825 return returnNode; 826 } 827 828 833 834 public void copyFields(Predicate otherPred) { 835 836 this.equivalenceClass = otherPred.getEquivalenceClass(); 837 this.indexPosition = otherPred.getIndexPosition(); 838 this.startKey = otherPred.isStartKey(); 839 this.stopKey = otherPred.isStopKey(); 840 this.isQualifier = otherPred.isQualifier(); 841 this.searchClauseHT = otherPred.getSearchClauseHT(); 842 843 } 844 845 848 849 public Hashtable getSearchClauseHT() { 850 return searchClauseHT; 851 } 852 853 864 protected boolean pushableToSubqueries() 865 throws StandardException 866 { 867 if (!isJoinPredicate()) 868 return false; 869 870 880 BinaryRelationalOperatorNode opNode = 881 (BinaryRelationalOperatorNode)getAndNode().getLeftOperand(); 882 883 JBitSet tNums = new JBitSet(getReferencedSet().size()); 884 BaseTableNumbersVisitor btnVis = new BaseTableNumbersVisitor(tNums); 885 opNode.getLeftOperand().accept(btnVis); 886 if (tNums.getFirstSetBit() == -1) 887 return false; 888 889 tNums.clearAll(); 890 opNode.getRightOperand().accept(btnVis); 891 if (tNums.getFirstSetBit() == -1) 892 return false; 893 894 return true; 895 } 896 897 904 protected boolean isJoinPredicate() 905 { 906 if (!(getAndNode().getLeftOperand() 909 instanceof BinaryRelationalOperatorNode)) 910 { 911 return false; 912 } 913 914 BinaryRelationalOperatorNode opNode = 915 (BinaryRelationalOperatorNode)getAndNode().getLeftOperand(); 916 917 return ((opNode.getLeftOperand() instanceof ColumnReference) && 920 (opNode.getRightOperand() instanceof ColumnReference) && 921 (((ColumnReference)opNode.getLeftOperand()).getTableNumber() != 922 ((ColumnReference)opNode.getRightOperand()).getTableNumber())); 923 } 924 925 978 protected Predicate getPredScopedForResultSet( 979 JBitSet parentRSNsTables, ResultSetNode childRSN, 980 int [] whichRC) throws StandardException 981 { 982 if (!(getAndNode().getLeftOperand() 984 instanceof BinaryRelationalOperatorNode)) 985 { 986 return this; 987 } 988 989 ValueNode trueNode = (ValueNode) getNodeFactory().getNode( 994 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 995 Boolean.TRUE, 996 getContextManager()); 997 998 BinaryRelationalOperatorNode opNode = 999 (BinaryRelationalOperatorNode)getAndNode().getLeftOperand(); 1000 1001 BinaryRelationalOperatorNode newOpNode = 1004 (BinaryRelationalOperatorNode) getNodeFactory().getNode( 1005 opNode.getNodeType(), 1006 opNode.getScopedOperand( 1007 BinaryRelationalOperatorNode.LEFT, 1008 parentRSNsTables, 1009 childRSN, 1010 whichRC), 1011 opNode.getScopedOperand( 1012 BinaryRelationalOperatorNode.RIGHT, 1013 parentRSNsTables, 1014 childRSN, 1015 whichRC), 1016 getContextManager()); 1017 1018 newOpNode.bindComparisonOperator(); 1020 1021 AndNode newAnd = (AndNode) getNodeFactory().getNode( 1024 C_NodeTypes.AND_NODE, 1025 newOpNode, 1026 trueNode, 1027 getContextManager()); 1028 newAnd.postBindFixup(); 1029 1030 JBitSet tableMap = new JBitSet( 1035 childRSN.getReferencedTableMap().size()); 1036 newAnd.categorize(tableMap, false); 1037 1038 Predicate newPred = (Predicate) getNodeFactory().getNode( 1040 C_NodeTypes.PREDICATE, 1041 newAnd, 1042 tableMap, 1043 getContextManager()); 1044 1045 newPred.clearScanFlags(); 1047 newPred.copyFields(this); 1048 newPred.setPushable(getPushable()); 1049 1050 newPred.markAsScopedForPush(); 1054 return newPred; 1055 } 1056 1057 1062 protected void markAsScopedForPush() { 1063 this.scoped = true; 1064 } 1065 1066 1070 protected boolean isScopedForPush() { 1071 return scoped; 1072 } 1073 1074 1140 protected boolean remapScopedPred() 1141 { 1142 if (!scoped) 1143 return false; 1144 1145 1153 BinaryRelationalOperatorNode binRelOp = 1154 (BinaryRelationalOperatorNode)andNode.getLeftOperand(); 1155 1156 ValueNode operand = null; 1157 1158 if (SanityManager.DEBUG) 1159 { 1160 1166 operand = binRelOp.getLeftOperand(); 1167 boolean leftIsScoped = 1168 !(operand instanceof ColumnReference) || 1169 ((ColumnReference)operand).isScoped(); 1170 1171 operand = binRelOp.getRightOperand(); 1172 boolean rightIsScoped = 1173 !(operand instanceof ColumnReference) || 1174 ((ColumnReference)operand).isScoped(); 1175 1176 SanityManager.ASSERT(leftIsScoped ^ rightIsScoped, 1177 "All scoped predicates should have exactly one scoped " + 1178 "operand, but '" + binaryRelOpColRefsToString() + 1179 "' has " + (leftIsScoped ? "TWO" : "NONE") + "."); 1180 } 1181 1182 operand = binRelOp.getLeftOperand(); 1184 if ((operand instanceof ColumnReference) && 1185 ((ColumnReference)operand).isScoped()) 1186 { 1187 ((ColumnReference)operand).remapColumnReferences(); 1189 } 1190 else 1191 { 1192 operand = binRelOp.getRightOperand(); 1193 if ((operand instanceof ColumnReference) && 1194 ((ColumnReference)operand).isScoped()) 1195 { 1196 ((ColumnReference)operand).remapColumnReferences(); 1198 } 1199 1200 } 1204 1205 return true; 1206 } 1207 1208 1236 protected boolean isScopedToSourceResultSet() 1237 throws StandardException 1238 { 1239 if (!scoped) 1240 return false; 1241 1242 1250 BinaryRelationalOperatorNode binRelOp = 1251 (BinaryRelationalOperatorNode)andNode.getLeftOperand(); 1252 1253 ValueNode operand = binRelOp.getLeftOperand(); 1254 1255 1264 if (!(operand instanceof ColumnReference)) 1265 return false; 1266 1267 1274 ValueNode exp = null; 1275 ColumnReference cRef = (ColumnReference)operand; 1276 if (cRef.isScoped()) 1277 { 1278 exp = cRef.getSource().getExpression(); 1279 return ((exp instanceof VirtualColumnNode) || 1280 (exp instanceof ColumnReference)); 1281 } 1282 1283 operand = binRelOp.getRightOperand(); 1284 if (!(operand instanceof ColumnReference)) 1285 return false; 1286 1287 cRef = (ColumnReference)operand; 1288 if (SanityManager.DEBUG) 1289 { 1290 SanityManager.ASSERT(cRef.isScoped(), 1293 "All scoped predicates should have exactly one scoped " + 1294 "operand, but '" + binaryRelOpColRefsToString() + 1295 "has NONE."); 1296 } 1297 1298 exp = cRef.getSource().getExpression(); 1299 return ((exp instanceof VirtualColumnNode) || 1300 (exp instanceof ColumnReference)); 1301 } 1302} 1303 | Popular Tags |