1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.loader.GeneratedMethod; 25 26 import org.apache.derby.iapi.services.compiler.MethodBuilder; 27 import org.apache.derby.iapi.services.compiler.LocalField; 28 import org.apache.derby.iapi.reference.ClassName; 29 import org.apache.derby.iapi.services.classfile.VMOpcode; 30 31 32 import org.apache.derby.iapi.error.StandardException; 33 34 import org.apache.derby.iapi.sql.compile.CompilerContext; 35 import org.apache.derby.iapi.sql.compile.ExpressionClassBuilderInterface; 36 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 37 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 38 import org.apache.derby.iapi.sql.compile.Optimizable; 39 import org.apache.derby.iapi.sql.compile.AccessPath; 40 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 41 42 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 43 44 import org.apache.derby.iapi.sql.execute.ExecIndexRow; 45 import org.apache.derby.iapi.sql.execute.ExecutionFactory; 46 47 import org.apache.derby.iapi.sql.Activation; 48 import org.apache.derby.iapi.sql.Row; 49 50 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 51 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 52 import org.apache.derby.iapi.sql.dictionary.StatisticsDescriptor; 53 import org.apache.derby.iapi.types.DataValueDescriptor; 54 import org.apache.derby.iapi.types.DataValueDescriptor; 55 56 import org.apache.derby.iapi.store.access.Qualifier; 57 import org.apache.derby.iapi.store.access.ScanController; 58 59 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 60 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 61 62 import org.apache.derby.iapi.services.sanity.SanityManager; 63 64 import org.apache.derby.iapi.util.JBitSet; 65 66 import java.lang.reflect.Modifier ; 67 68 import java.sql.Types ; 69 70 import java.util.ArrayList ; 71 import java.util.Enumeration ; 72 import java.util.Properties ; 73 import java.util.Vector ; 74 75 83 84 public class PredicateList extends QueryTreeNodeVector implements OptimizablePredicateList 85 { 86 private int numberOfStartPredicates; 87 private int numberOfStopPredicates; 88 private int numberOfQualifiers; 89 90 public PredicateList() 91 { 92 } 93 94 97 98 101 public OptimizablePredicate getOptPredicate(int index) 102 { 103 return (OptimizablePredicate) elementAt(index); 104 } 105 106 111 public final void removeOptPredicate(int predCtr) throws StandardException 112 { 113 Predicate predicate = (Predicate) remove(predCtr); 114 115 if (predicate.isStartKey()) 116 numberOfStartPredicates--; 117 if (predicate.isStopKey()) 118 numberOfStopPredicates--; 119 if (predicate.isQualifier()) 120 numberOfQualifiers--; 121 } 122 123 128 public final void removeOptPredicate(OptimizablePredicate pred) 129 { 130 removeElement((Predicate) pred); 131 132 if (pred.isStartKey()) 133 numberOfStartPredicates--; 134 if (pred.isStopKey()) 135 numberOfStopPredicates--; 136 if (pred.isQualifier()) 137 numberOfQualifiers--; 138 } 139 140 141 142 public void addOptPredicate(OptimizablePredicate optPredicate) 143 { 144 addElement((Predicate)optPredicate); 145 146 if (optPredicate.isStartKey()) 147 numberOfStartPredicates++; 148 if (optPredicate.isStopKey()) 149 numberOfStopPredicates++; 150 if (optPredicate.isQualifier()) 151 numberOfQualifiers++; 152 } 153 154 158 public void addOptPredicate(OptimizablePredicate optPredicate, int position) 159 { 160 insertElementAt((Predicate) optPredicate, position); 161 162 if (optPredicate.isStartKey()) 163 numberOfStartPredicates++; 164 if (optPredicate.isStopKey()) 165 numberOfStopPredicates++; 166 if (optPredicate.isQualifier()) 167 numberOfQualifiers++; 168 } 169 170 171 175 public boolean useful(Optimizable optTable, ConglomerateDescriptor cd) 176 throws StandardException 177 { 178 boolean retval = false; 179 180 184 185 186 if ( ! cd.isIndex()) 187 return false; 188 189 195 int size = size(); 196 for (int index = 0; index < size; index++) 197 { 198 Predicate pred = (Predicate) elementAt(index); 199 200 204 RelationalOperator relop = pred.getRelop(); 205 boolean isIn = false; 206 InListOperatorNode inNode = null; 207 208 if (relop == null) 209 { 210 213 if (pred.getAndNode().getLeftOperand() instanceof InListOperatorNode && 214 ! ((InListOperatorNode)pred.getAndNode().getLeftOperand()).getTransformed()) 215 { 216 isIn = true; 217 inNode = (InListOperatorNode) pred.getAndNode().getLeftOperand(); 218 } 219 else 220 continue; 221 } 222 223 228 if ( (! isIn) && ( ! relop.usefulStartKey(optTable) ) && 229 ( ! relop.usefulStopKey(optTable) ) ) 230 { 231 continue; 232 } 233 234 238 ColumnReference indexCol = null; 239 240 if (isIn) 241 { 242 if (inNode.getLeftOperand() instanceof ColumnReference) 243 { 244 indexCol = (ColumnReference) inNode.getLeftOperand(); 245 if (indexCol.getColumnNumber() != 246 cd.getIndexDescriptor().baseColumnPositions()[0]) 247 { 248 indexCol = null; 249 } 250 } 251 } 252 else 253 { 254 indexCol = 255 relop.getColumnOperand( 256 optTable, 257 cd.getIndexDescriptor().baseColumnPositions()[0]); 258 } 259 260 if (indexCol == null) 261 { 262 continue; 263 } 264 265 270 if ((isIn && inNode.selfReference(indexCol)) || 271 (! isIn && relop.selfComparison(indexCol))) 272 { 273 continue; 274 } 275 276 277 retval = true; 278 break; 279 } 280 281 return retval; 282 } 283 284 289 public void pushUsefulPredicates(Optimizable optTable) 290 throws StandardException 291 { 292 AccessPath ap = optTable.getTrulyTheBestAccessPath(); 293 294 orderUsefulPredicates(optTable, 295 ap.getConglomerateDescriptor(), 296 true, 297 ap.getNonMatchingIndexScan(), 298 ap.getCoveringIndexScan()); 299 } 300 301 306 public void classify(Optimizable optTable, ConglomerateDescriptor cd) 307 throws StandardException 308 { 309 316 orderUsefulPredicates(optTable, cd, false, false, false); 317 } 318 319 320 public void markAllPredicatesQualifiers() 321 { 322 int size = size(); 323 for (int index = 0; index < size; index++) 324 { 325 ((Predicate) elementAt(index)).markQualifier(); 326 } 327 328 numberOfQualifiers = size; 329 } 330 331 336 public boolean hasOptimizableEqualityPredicate(Optimizable optTable, 337 int columnNumber, 338 boolean isNullOkay) 339 throws StandardException 340 { 341 int size = size(); 342 for (int index = 0; index < size; index++) 343 { 344 AndNode andNode; 345 Predicate predicate; 346 predicate = (Predicate) elementAt(index); 347 348 andNode = (AndNode) predicate.getAndNode(); 349 350 ValueNode opNode = andNode.getLeftOperand(); 352 353 if (opNode.optimizableEqualityNode(optTable, 354 columnNumber, 355 isNullOkay)) 356 { 357 return true; 358 } 359 } 360 361 return false; 362 } 363 364 369 public boolean hasOptimizableEquijoin(Optimizable optTable, 370 int columnNumber) 371 throws StandardException 372 { 373 int size = size(); 374 for (int index = 0; index < size; index++) 375 { 376 AndNode andNode; 377 Predicate predicate; 378 predicate = (Predicate) elementAt(index); 379 380 if (predicate.isScopedForPush()) 390 { 391 continue; 392 } 393 394 andNode = (AndNode) predicate.getAndNode(); 395 396 ValueNode opNode = andNode.getLeftOperand(); 397 398 if ( ! opNode.optimizableEqualityNode(optTable, 399 columnNumber, 400 false)) 401 { 402 continue; 403 } 404 405 409 if ( ! ((RelationalOperator) opNode).isQualifier(optTable, false)) 410 { 411 continue; 412 } 413 414 417 if (predicate.getReferencedMap().hasSingleBitSet()) 418 { 419 continue; 420 } 421 422 return true; 424 } 425 426 return false; 427 } 428 429 434 public void putOptimizableEqualityPredicateFirst(Optimizable optTable, 435 int columnNumber) 436 throws StandardException 437 { 438 int size = size(); 439 for (int index = 0; index < size; index++) 440 { 441 Predicate predicate = (Predicate) elementAt(index); 442 AndNode andNode; 443 444 andNode = (AndNode) predicate.getAndNode(); 445 446 ValueNode opNode = andNode.getLeftOperand(); 448 449 if (!opNode.optimizableEqualityNode(optTable, columnNumber, false)) 450 continue; 451 452 if (index != 0) 454 { 455 removeElementAt(index); 456 insertElementAt(predicate, 0); 457 } 458 459 return; 460 } 461 462 465 if (SanityManager.DEBUG) 466 { 467 SanityManager.THROWASSERT( 468 "Could not find the expected equality predicate on column #" + 469 columnNumber); 470 } 471 } 472 473 private void orderUsefulPredicates(Optimizable optTable, 474 ConglomerateDescriptor cd, 475 boolean pushPreds, 476 boolean nonMatchingIndexScan, 477 boolean coveringIndexScan) 478 throws StandardException 479 { 480 boolean[] deletes; 481 int[] baseColumnPositions; 482 boolean[] isAscending; 483 int size = size(); 484 Predicate[] usefulPredicates = new Predicate[size]; 485 int usefulCount = 0; 486 Predicate predicate; 487 488 489 493 for (int index = 0; index < size; index++) 494 { 495 predicate = (Predicate) elementAt(index); 496 497 predicate.clearScanFlags(); 498 } 499 500 507 508 509 if ((cd == null) || (! cd.isIndex()) || 510 (nonMatchingIndexScan && coveringIndexScan)) 511 { 512 527 Predicate[] preds = new Predicate[size]; 528 529 for (int index = 0; index < size; index++) 530 { 531 Predicate pred = (Predicate) elementAt(index); 532 533 537 RelationalOperator relop = pred.getRelop(); 538 539 if (relop == null) 540 { 541 543 if (!pred.isPushableOrClause(optTable)) 544 { 545 continue; 547 } 548 } 549 else 550 { 551 if ( ! relop.isQualifier(optTable, pushPreds)) 552 { 553 continue; 555 } 556 } 557 558 pred.markQualifier(); 559 560 if (pushPreds) 561 { 562 565 if (optTable.pushOptPredicate(pred)) 566 { 567 preds[index] = pred; 568 } 569 } 570 } 571 572 573 for (int inner = size - 1; inner >= 0; inner--) 574 { 575 if (preds[inner] != null) 576 { 577 removeOptPredicate(preds[inner]); 578 } 579 } 580 581 return; 582 } 583 584 baseColumnPositions = cd.getIndexDescriptor().baseColumnPositions(); 585 isAscending = cd.getIndexDescriptor().isAscending(); 586 587 591 for (int index = 0; index < size; index++) 592 { 593 Predicate pred = (Predicate) elementAt(index); 594 ColumnReference indexCol = null; 595 int indexPosition; 596 597 601 RelationalOperator relop = pred.getRelop(); 602 603 606 boolean isIn = false; 607 InListOperatorNode inNode = null; 608 609 if (relop == null) 610 { 611 if (pred.getAndNode().getLeftOperand() instanceof InListOperatorNode && 612 ! ((InListOperatorNode)pred.getAndNode().getLeftOperand()).getTransformed()) 613 { 614 isIn = true; 615 inNode = (InListOperatorNode) pred.getAndNode().getLeftOperand(); 616 } 617 else 618 continue; 619 } 620 621 if ( !isIn && ! relop.isQualifier(optTable, pushPreds)) 622 continue; 623 624 625 for (indexPosition = 0; 626 indexPosition < baseColumnPositions.length; 627 indexPosition++) 628 { 629 if (isIn) 630 { 631 if (inNode.getLeftOperand() instanceof ColumnReference) 632 { 633 indexCol = (ColumnReference) inNode.getLeftOperand(); 634 if ((optTable.getTableNumber() != indexCol.getTableNumber()) || 635 (indexCol.getColumnNumber() != baseColumnPositions[indexPosition]) || 636 inNode.selfReference(indexCol)) 637 indexCol = null; 638 } 639 } 640 else 641 { 642 indexCol = 643 relop.getColumnOperand( 644 optTable, 645 baseColumnPositions[indexPosition]); 646 } 647 if (indexCol != null) 648 break; 649 } 650 651 655 if (indexCol == null) 656 continue; 657 658 pred.setIndexPosition(indexPosition); 659 660 661 usefulPredicates[usefulCount++] = pred; 662 } 663 664 671 if (usefulCount == 0) 672 return; 673 674 675 if (usefulPredicates.length > usefulCount) 676 { 677 Predicate[] shrink = new Predicate[usefulCount]; 678 679 System.arraycopy(usefulPredicates, 0, shrink, 0, usefulCount); 680 681 usefulPredicates = shrink; 682 } 683 684 685 java.util.Arrays.sort(usefulPredicates); 686 687 688 int currentStartPosition = -1; 689 boolean gapInStartPositions = false; 690 int currentStopPosition = -1; 691 boolean gapInStopPositions = false; 692 boolean seenNonEquals = false; 693 int firstNonEqualsPosition = -1; 694 int lastStartEqualsPosition = -1; 695 696 707 boolean seenGE = false, seenGT = false; 708 709 for (int i = 0; i < usefulCount; i++) 710 { 711 Predicate thisPred = usefulPredicates[i]; 712 int thisIndexPosition = thisPred.getIndexPosition(); 713 boolean thisPredMarked = false; 714 RelationalOperator relop = thisPred.getRelop(); 715 int thisOperator = -1; 716 717 boolean isIn = false; 718 InListOperatorNode inNode = null; 719 720 if (relop == null) 721 { 722 isIn = true; 723 inNode = (InListOperatorNode) 724 thisPred.getAndNode().getLeftOperand(); 725 } 726 else 727 { 728 thisOperator = relop.getOperator(); 729 } 730 731 732 if (currentStartPosition != thisIndexPosition) 733 { 734 738 if ((thisIndexPosition - currentStartPosition) > 1) 739 { 740 744 gapInStartPositions = true; 745 } 746 else if ((thisOperator == RelationalOperator.EQUALS_RELOP) || 747 (thisOperator == RelationalOperator.IS_NULL_RELOP)) 748 { 749 754 lastStartEqualsPosition = thisIndexPosition; 755 } 756 757 if ( ! gapInStartPositions) 758 { 759 770 if (! seenGT && 771 (isIn || ((relop.usefulStartKey(optTable) && isAscending[thisIndexPosition]) || 772 (relop.usefulStopKey(optTable) && ! isAscending[thisIndexPosition])))) 773 { 774 thisPred.markStartKey(); 775 currentStartPosition = thisIndexPosition; 776 thisPredMarked = true; 777 seenGT = (thisPred.getStartOperator(optTable) == ScanController.GT); 778 } 779 } 780 } 781 782 783 if (currentStopPosition != thisIndexPosition) 784 { 785 if ((thisIndexPosition - currentStopPosition) > 1) 786 { 787 gapInStopPositions = true; 788 } 789 790 if ( ! gapInStopPositions) 791 { 792 if (! seenGE && 793 (isIn || ((relop.usefulStopKey(optTable) && isAscending[thisIndexPosition]) || 794 (relop.usefulStartKey(optTable) && ! isAscending[thisIndexPosition])))) 795 { 796 thisPred.markStopKey(); 797 currentStopPosition = thisIndexPosition; 798 thisPredMarked = true; 799 seenGE = (thisPred.getStopOperator(optTable) == ScanController.GE); 800 } 801 } 802 } 803 804 811 if ( (! isIn) && ((! thisPredMarked ) || 813 (seenNonEquals && thisIndexPosition != firstNonEqualsPosition) 814 ) ) 815 { 816 thisPred.markQualifier(); 817 } 818 819 820 if (lastStartEqualsPosition != thisIndexPosition && 821 firstNonEqualsPosition == -1 && 822 (thisOperator != RelationalOperator.EQUALS_RELOP) && 823 (thisOperator != RelationalOperator.IS_NULL_RELOP)) 824 { 825 seenNonEquals = true; 826 827 firstNonEqualsPosition = thisIndexPosition; 828 } 829 830 if (pushPreds) 831 { 832 838 if (isIn && ! thisPredMarked) 839 continue; 840 841 845 846 856 Predicate predToPush; 857 if (isIn) 858 { 859 AndNode andCopy = (AndNode) getNodeFactory().getNode( 860 C_NodeTypes.AND_NODE, 861 thisPred.getAndNode().getLeftOperand(), 862 thisPred.getAndNode().getRightOperand(), 863 getContextManager()); 864 andCopy.copyFields(thisPred.getAndNode()); 865 Predicate predCopy = (Predicate) getNodeFactory().getNode( 866 C_NodeTypes.PREDICATE, 867 andCopy, 868 thisPred.getReferencedSet(), 869 getContextManager()); 870 predCopy.copyFields(thisPred); 871 predToPush = predCopy; 872 } 873 else 874 { 875 predToPush = thisPred; 876 } 877 878 if (optTable.pushOptPredicate(predToPush)) 879 { 880 883 if (! isIn) 884 removeOptPredicate(thisPred); 885 } 887 else if (SanityManager.DEBUG) 888 { 889 SanityManager.ASSERT(false, 890 "pushOptPredicate expected to be true"); 891 } 892 } 893 else 894 { 895 899 removeOptPredicate(thisPred); 900 addOptPredicate(thisPred, i); 901 } 902 } 903 } 904 905 912 913 public void addPredicate(Predicate predicate) throws StandardException 914 { 915 if (predicate.isStartKey()) 916 numberOfStartPredicates++; 917 if (predicate.isStopKey()) 918 numberOfStopPredicates++; 919 if (predicate.isQualifier()) 920 numberOfQualifiers++; 921 922 addElement(predicate); 923 } 924 925 937 protected void transferNonQualifiers(Optimizable optTable, PredicateList otherPL) 938 throws StandardException 939 { 940 943 for (int index = size() - 1; index >= 0; index--) 944 { 945 Predicate pred = (Predicate) elementAt(index); 946 947 RelationalOperator relop = pred.getRelop(); 948 if (relop == null || ! relop.isQualifier(optTable, false)) 950 { 951 pred.clearScanFlags(); 952 removeElementAt(index); 953 otherPL.addElement(pred); 954 } 955 } 956 957 markAllPredicatesQualifiers(); 959 } 960 961 967 public void categorize() 968 throws StandardException 969 { 970 int size = size(); 971 972 for (int index = 0; index < size; index++) 973 { 974 ((Predicate) elementAt(index)).categorize(); 975 } 976 } 977 978 979 985 986 public void printSubNodes(int depth) 987 { 988 if (SanityManager.DEBUG) 989 { 990 Predicate predicate; 991 992 super.printSubNodes(depth); 993 994 for (int index = 0; index < size(); index++) 995 { 996 predicate = (Predicate) elementAt(index); 997 predicate.treePrint(depth + 1); 998 } 999 } 1000 } 1001 1002 1011 public void eliminateBooleanTrueAndBooleanTrue() 1012 { 1013 1016 for (int index = size() - 1; index >= 0; index--) 1017 { 1018 AndNode nextAnd; 1019 1020 nextAnd = ((Predicate) elementAt(index)).getAndNode(); 1021 1022 if ((nextAnd.getLeftOperand().isBooleanTrue()) && 1023 (nextAnd.getRightOperand().isBooleanTrue())) 1024 { 1025 removeElementAt(index); 1026 } 1027 } 1028 1029 } 1030 1031 1057 public ValueNode restoreConstantPredicates() 1058 throws StandardException 1059 { 1060 AndNode nextAnd; 1061 AndNode falseAnd = null; 1062 ValueNode restriction = null; 1063 1064 1067 for (int index = size() - 1; index >= 0; index--) 1068 { 1069 1070 nextAnd = ((Predicate) elementAt(index)).getAndNode(); 1071 1072 if (! nextAnd.isConstantExpression()) 1074 { 1075 continue; 1076 } 1077 1078 removeElementAt(index); 1080 1081 1082 if ((nextAnd.getLeftOperand().isBooleanTrue()) && 1083 (nextAnd.getRightOperand().isBooleanTrue())) 1084 { 1085 continue; 1086 } 1087 1088 1089 if (nextAnd.getLeftOperand().isBooleanFalse()) 1090 { 1091 falseAnd = nextAnd; 1092 } 1093 1094 if (restriction != null) 1095 { 1096 nextAnd.setRightOperand(restriction); 1097 1100 if (restriction.getTypeServices().isNullable()) 1101 { 1102 nextAnd.getTypeServices().setNullability(true); 1103 } 1104 } 1105 restriction = nextAnd; 1106 } 1107 1108 1112 if ((restriction != null) && 1113 (((AndNode) restriction).getRightOperand().isBooleanTrue())) 1114 { 1115 restriction = ((AndNode) restriction).getLeftOperand(); 1116 } 1117 else if (falseAnd != null) 1118 { 1119 1122 restriction = falseAnd.getLeftOperand(); 1123 } 1124 1125 return restriction; 1126 } 1127 1128 1154 public ValueNode restorePredicates() 1155 throws StandardException 1156 { 1157 AndNode nextAnd; 1158 AndNode falseAnd = null; 1159 ValueNode restriction = null; 1160 1161 int size = size(); 1162 for (int index = 0; index < size; index++) 1163 { 1164 nextAnd = ((Predicate) elementAt(index)).getAndNode(); 1165 1166 1167 if ((nextAnd.getLeftOperand().isBooleanTrue()) && 1168 (nextAnd.getRightOperand().isBooleanTrue())) 1169 { 1170 continue; 1171 } 1172 1173 1174 if (nextAnd.getLeftOperand().isBooleanFalse()) 1175 { 1176 falseAnd = nextAnd; 1177 } 1178 1179 if (restriction != null) 1180 { 1181 nextAnd.setRightOperand(restriction); 1182 1185 if (restriction.getTypeServices().isNullable()) 1186 { 1187 nextAnd.getTypeServices().setNullability(true); 1188 } 1189 } 1190 restriction = nextAnd; 1191 } 1192 1193 1197 if ((restriction != null) && 1198 (((AndNode) restriction).getRightOperand().isBooleanTrue())) 1199 { 1200 restriction = ((AndNode) restriction).getLeftOperand(); 1201 } 1202 else if (falseAnd != null) 1203 { 1204 1208 restriction = falseAnd.getLeftOperand(); 1209 } 1210 1211 1212 removeAllElements(); 1213 return restriction; 1214 } 1215 1216 1222 public void remapColumnReferencesToExpressions() throws StandardException 1223 { 1224 Predicate pred; 1225 1226 int size = size(); 1227 for (int index = 0; index < size; index++) 1228 { 1229 pred = (Predicate) elementAt(index); 1230 1231 pred.setAndNode((AndNode) 1232 pred.getAndNode().remapColumnReferencesToExpressions()); 1233 } 1234 } 1235 1236 1250 void pullExpressions(int numTables, 1251 ValueNode searchClause) 1252 throws StandardException 1253 { 1254 AndNode thisAnd; 1255 AndNode topAnd; 1256 JBitSet newJBitSet; 1257 Predicate newPred; 1258 BooleanConstantNode trueNode = null; 1259 1260 if (searchClause != null) 1261 { 1262 topAnd = (AndNode) searchClause; 1263 searchClause = null; 1264 trueNode = (BooleanConstantNode) getNodeFactory().getNode( 1265 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 1266 Boolean.TRUE, 1267 getContextManager()); 1268 1269 while (topAnd.getRightOperand() instanceof AndNode) 1270 { 1271 1272 thisAnd = topAnd; 1273 topAnd = (AndNode) topAnd.getRightOperand(); 1274 thisAnd.setRightOperand(null); 1275 1276 1277 thisAnd.setRightOperand(trueNode); 1278 1279 1280 newJBitSet = new JBitSet(numTables); 1281 newPred = (Predicate) getNodeFactory().getNode( 1282 C_NodeTypes.PREDICATE, 1283 thisAnd, 1284 newJBitSet, 1285 getContextManager()); 1286 addPredicate(newPred); 1287 } 1288 1289 1290 newJBitSet = new JBitSet(numTables); 1291 newPred = (Predicate) getNodeFactory().getNode( 1292 C_NodeTypes.PREDICATE, 1293 topAnd, 1294 newJBitSet, 1295 getContextManager()); 1296 addPredicate(newPred); 1297 } 1298 } 1299 1300 1307 public void xorReferencedSet(JBitSet fromMap) 1308 { 1309 Predicate predicate; 1310 1311 int size = size(); 1312 for (int index = 0; index < size; index++) 1313 { 1314 predicate = (Predicate) elementAt(index); 1315 1316 if (SanityManager.DEBUG) 1317 { 1318 SanityManager.ASSERT( 1319 fromMap.size() == predicate.getReferencedSet().size(), 1320 "fromMap.size() (" + fromMap.size() + 1321 ") does not equal predicate.getReferencedSet().size() (" + 1322 predicate.getReferencedSet().size()); 1323 } 1324 1325 predicate.getReferencedSet().xor(fromMap); 1326 } 1327 } 1328 1329 private void countScanFlags() 1330 { 1331 Predicate predicate; 1332 1333 int size = size(); 1334 for (int index = 0; index < size; index++) 1335 { 1336 predicate = (Predicate) elementAt(index); 1337 if (predicate.isStartKey()) 1338 numberOfStartPredicates++; 1339 if (predicate.isStopKey()) 1340 numberOfStopPredicates++; 1341 if (predicate.isQualifier()) 1342 numberOfQualifiers++; 1343 } 1344 } 1345 1346 1360 void pushExpressionsIntoSelect(SelectNode select, boolean copyPredicate) 1361 throws StandardException 1362 { 1363 1366 for (int index = size() - 1; index >= 0; index--) 1367 { 1368 Predicate predicate; 1369 predicate = (Predicate) elementAt(index); 1370 1371 CollectNodesVisitor getCRs = 1372 new CollectNodesVisitor(ColumnReference.class); 1373 1374 predicate.getAndNode().accept(getCRs); 1375 Vector colRefs = getCRs.getList(); 1376 1377 1381 boolean state = colRefs.size() > 0; 1382 if (state) 1383 { 1384 for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) 1385 { 1386 ColumnReference ref = (ColumnReference)e.nextElement(); 1387 if (!ref.pointsToColumnReference()) 1388 { 1389 state = false; 1390 break; 1391 } 1392 } 1393 } 1394 1395 if (!state) 1396 continue; 1397 1398 if (copyPredicate) 1399 { 1400 AndNode andNode = predicate.getAndNode(); 1402 ValueNode leftOperand; 1403 ColumnReference crNode; 1404 BinaryRelationalOperatorNode opNode=null; 1405 InListOperatorNode inNode=null; 1406 1407 1411 if (andNode.getLeftOperand() instanceof BinaryRelationalOperatorNode) 1412 { 1413 opNode = (BinaryRelationalOperatorNode) andNode.getLeftOperand(); 1414 if (! (opNode.getLeftOperand() instanceof ColumnReference) || 1416 ! (opNode.getRightOperand() instanceof ConstantNode || 1417 opNode.getRightOperand() instanceof ParameterNode)) 1418 continue; 1419 1420 crNode = (ColumnReference) opNode.getLeftOperand(); 1421 } 1422 else if (andNode.getLeftOperand() instanceof InListOperatorNode) 1423 { 1424 inNode = (InListOperatorNode) andNode.getLeftOperand(); 1425 if (! (inNode.getRightOperandList().isConstantExpression())) 1426 continue; 1427 1428 crNode = (ColumnReference) inNode.getLeftOperand(); 1429 } 1430 else 1431 continue; 1432 1433 ColumnReference newCRNode = select.findColumnReferenceInResult(crNode.columnName); 1435 if (newCRNode == null) 1436 continue; 1437 1438 if (andNode.getLeftOperand() instanceof BinaryRelationalOperatorNode) 1441 { 1442 BinaryRelationalOperatorNode newRelop = (BinaryRelationalOperatorNode) 1443 getNodeFactory().getNode( 1444 opNode.getNodeType(), 1445 newCRNode, 1446 opNode.getRightOperand(), 1447 getContextManager()); 1448 newRelop.bindComparisonOperator(); 1449 leftOperand = newRelop; 1450 } 1451 else 1452 { 1453 InListOperatorNode newInNode = (InListOperatorNode) 1454 getNodeFactory().getNode( 1455 C_NodeTypes.IN_LIST_OPERATOR_NODE, 1456 newCRNode, 1457 inNode.getRightOperandList(), 1458 getContextManager()); 1459 newInNode.setType(inNode.getTypeServices()); 1460 leftOperand = newInNode; 1461 } 1462 1463 ValueNode trueNode = (ValueNode) getNodeFactory().getNode( 1465 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 1466 Boolean.TRUE, 1467 getContextManager()); 1468 AndNode newAnd = (AndNode) getNodeFactory().getNode( 1469 C_NodeTypes.AND_NODE, 1470 leftOperand, 1471 trueNode, 1472 getContextManager()); 1473 newAnd.postBindFixup(); 1474 JBitSet tableMap = new JBitSet(select.referencedTableMap.size()); 1475 1476 predicate = (Predicate) getNodeFactory().getNode( 1478 C_NodeTypes.PREDICATE, 1479 newAnd, 1480 tableMap, 1481 getContextManager()); 1482 } 1483 else 1484 { 1485 if (predicate.isStartKey()) 1487 numberOfStartPredicates--; 1488 if (predicate.isStopKey()) 1489 numberOfStopPredicates--; 1490 if (predicate.isQualifier()) 1491 numberOfQualifiers--; 1492 1493 1496 predicate.clearScanFlags(); 1497 removeElementAt(index); 1499 } 1500 1501 select.pushExpressionsIntoSelect(predicate); 1503 } 1504 } 1505 1506 1512 void markReferencedColumns() 1513 throws StandardException 1514 { 1515 CollectNodesVisitor collectCRs = 1516 new CollectNodesVisitor(ColumnReference.class); 1517 1518 int size = size(); 1519 for (int index = 0; index < size; index++) 1520 { 1521 Predicate predicate = (Predicate) elementAt(index); 1522 predicate.getAndNode().accept(collectCRs); 1523 } 1524 1525 Vector colRefs = collectCRs.getList(); 1526 for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) 1527 { 1528 ColumnReference ref = (ColumnReference)e.nextElement(); 1529 ref.getSource().markAllRCsInChainReferenced(); 1530 } 1531 } 1532 1533 1549 void checkTopPredicatesForEqualsConditions( 1550 int tableNumber, 1551 boolean[] eqOuterCols, 1552 int[] tableNumbers, 1553 JBitSet[] tableColMap, 1554 boolean resultColTable) 1555 throws StandardException 1556 { 1557 int size = size(); 1558 for (int index = 0; index < size; index++) 1559 { 1560 AndNode and = (AndNode) ((Predicate) elementAt(index)).getAndNode(); 1561 and.checkTopPredicatesForEqualsConditions( 1562 tableNumber, eqOuterCols, tableNumbers, tableColMap, 1563 resultColTable); 1564 } 1565 } 1566 1567 1572 boolean allPushable() 1573 { 1574 int size = size(); 1575 for (int index = 0; index < size; index++) 1576 { 1577 Predicate predicate = (Predicate) elementAt(index); 1578 if (! predicate.getPushable()) 1579 { 1580 return false; 1581 } 1582 } 1583 return true; 1584 } 1585 1586 1597 PredicateList getPushablePredicates(JBitSet referencedTableMap) 1598 throws StandardException 1599 { 1600 PredicateList pushPList = null; 1601 1602 for (int index = size() - 1; index >= 0; index--) 1604 { 1605 Predicate predicate = (Predicate) elementAt(index); 1606 if (! predicate.getPushable()) 1607 { 1608 continue; 1609 } 1610 1611 JBitSet curBitSet = predicate.getReferencedSet(); 1612 1613 1614 if (referencedTableMap.contains(curBitSet)) 1615 { 1616 1617 if (pushPList == null) 1618 { 1619 pushPList = (PredicateList) getNodeFactory().getNode( 1620 C_NodeTypes.PREDICATE_LIST, 1621 getContextManager()); 1622 } 1623 pushPList.addPredicate(predicate); 1624 1625 1628 RemapCRsVisitor rcrv = new RemapCRsVisitor(true); 1629 predicate.getAndNode().accept(rcrv); 1630 1631 1632 removeElementAt(index); 1633 } 1634 } 1635 return pushPList; 1636 } 1637 1638 1645 void decrementLevel(FromList fromList, int decrement) 1646 { 1647 int[] tableNumbers = fromList.getTableNumbers(); 1648 1649 1653 int size = size(); 1654 for (int index = 0; index < size; index++) 1655 { 1656 ColumnReference cr1 = null; 1657 ColumnReference cr2 = null; 1658 Predicate predicate = (Predicate) elementAt(index); 1659 ValueNode vn = predicate.getAndNode().getLeftOperand(); 1660 1661 if (vn instanceof BinaryOperatorNode) 1662 { 1663 BinaryOperatorNode bon = (BinaryOperatorNode) vn; 1664 if (bon.getLeftOperand() instanceof ColumnReference) 1665 { 1666 cr1 = (ColumnReference) bon.getLeftOperand(); 1667 } 1668 if (bon.getRightOperand() instanceof ColumnReference) 1669 { 1670 cr2 = (ColumnReference) bon.getRightOperand(); 1671 } 1672 } 1673 else if (vn instanceof UnaryOperatorNode) 1674 { 1675 UnaryOperatorNode uon = (UnaryOperatorNode) vn; 1676 if (uon.getOperand() instanceof ColumnReference) 1677 { 1678 cr1 = (ColumnReference) uon.getOperand(); 1679 } 1680 } 1681 1682 1685 if (cr1 != null) 1686 { 1687 int sourceTable = cr1.getTableNumber(); 1688 for (int inner = 0; inner < tableNumbers.length; inner++) 1689 if (tableNumbers[inner] == sourceTable) 1690 { 1691 cr1.setSourceLevel( 1692 cr1.getSourceLevel() - decrement); 1693 break; 1694 } 1695 } 1696 1697 if (cr2 != null) 1698 { 1699 int sourceTable = cr2.getTableNumber(); 1700 for (int inner = 0; inner < tableNumbers.length; inner++) 1701 if (tableNumbers[inner] == sourceTable) 1702 { 1703 cr2.setSourceLevel( 1704 cr2.getSourceLevel() - decrement); 1705 break; 1706 } 1707 } 1708 } 1709 } 1710 1711 1733 void joinClauseTransitiveClosure(int numTables, 1734 FromList fromList, CompilerContext cc) 1735 throws StandardException 1736 { 1737 if (fromList.size() < 3) 1739 { 1740 return; 1741 } 1742 1743 1744 PredicateList[] joinClauses = new PredicateList[numTables]; 1745 for (int index = 0; index < numTables; index++) 1746 { 1747 joinClauses[index] = new PredicateList(); 1748 } 1749 1750 1753 int size = size(); 1754 for (int index = 0; index < size; index++) 1755 { 1756 Predicate predicate = (Predicate) elementAt(index); 1757 ValueNode vn = predicate.getAndNode().getLeftOperand(); 1758 1759 if (! (vn.isBinaryEqualsOperatorNode())) 1760 { 1761 continue; 1762 } 1763 1764 1765 BinaryRelationalOperatorNode equals = 1766 (BinaryRelationalOperatorNode) vn; 1767 ValueNode left = equals.getLeftOperand(); 1768 ValueNode right = equals.getRightOperand(); 1769 1770 if ((left instanceof ColumnReference && 1771 right instanceof ColumnReference)) 1772 { 1773 ColumnReference leftCR = (ColumnReference) left; 1774 ColumnReference rightCR = (ColumnReference) right; 1775 if (leftCR.getSourceLevel() == rightCR.getSourceLevel() && 1776 leftCR.getTableNumber() != rightCR.getTableNumber()) 1777 { 1778 joinClauses[leftCR.getTableNumber()].addElement(predicate); 1780 joinClauses[rightCR.getTableNumber()].addElement(predicate); 1781 } 1782 continue; 1783 } 1784 } 1785 1786 1789 for (int index = 0; index < numTables; index++) 1790 { 1791 PredicateList outerJCL = joinClauses[index]; 1792 1793 if (outerJCL.size() == 0) 1795 { 1796 continue; 1797 } 1798 1799 1802 Vector movePreds = new Vector (); 1803 for (int jcIndex = outerJCL.size() - 1; jcIndex >= 0; jcIndex--) 1804 { 1805 Predicate predicate = (Predicate) outerJCL.elementAt(jcIndex); 1806 if (predicate.getEquivalenceClass() != -1) 1807 { 1808 outerJCL.removeElementAt(jcIndex); 1809 movePreds.addElement(predicate); 1810 } 1811 } 1812 for (int mpIndex = 0; mpIndex < movePreds.size(); mpIndex++) 1813 { 1814 outerJCL.insertElementAt( 1815 (Predicate) movePreds.elementAt(mpIndex), 0); 1816 } 1817 1818 for (int outerIndex = 0; outerIndex < outerJCL.size(); outerIndex++) 1820 { 1821 ColumnReference innerCR = null; 1822 ColumnReference outerCR = null; 1823 int outerTableNumber = index; 1824 int middleTableNumber; 1825 int outerColumnNumber; 1826 int middleColumnNumber; 1827 int outerEC; 1828 1829 1832 Predicate outerP = (Predicate) outerJCL.elementAt(outerIndex); 1833 if (outerP.getEquivalenceClass() == -1) 1834 { 1835 outerP.setEquivalenceClass(cc.getNextEquivalenceClass()); 1836 } 1837 outerEC = outerP.getEquivalenceClass(); 1838 1839 BinaryRelationalOperatorNode equals = 1841 (BinaryRelationalOperatorNode) outerP.getAndNode().getLeftOperand(); 1842 ColumnReference leftCR = (ColumnReference) equals.getLeftOperand(); 1843 ColumnReference rightCR = (ColumnReference) equals.getRightOperand(); 1844 1845 if (leftCR.getTableNumber() == outerTableNumber) 1846 { 1847 outerColumnNumber = leftCR.getColumnNumber(); 1848 middleTableNumber = rightCR.getTableNumber(); 1849 middleColumnNumber = rightCR.getColumnNumber(); 1850 outerCR = leftCR; 1851 } 1852 else 1853 { 1854 outerColumnNumber = rightCR.getColumnNumber(); 1855 middleTableNumber = leftCR.getTableNumber(); 1856 middleColumnNumber = leftCR.getColumnNumber(); 1857 outerCR = rightCR; 1858 } 1859 1860 1863 PredicateList middleJCL = joinClauses[middleTableNumber]; 1864 for (int middleIndex = 0; middleIndex < middleJCL.size(); middleIndex++) 1865 { 1866 1869 Predicate middleP = (Predicate) middleJCL.elementAt(middleIndex); 1870 if (middleP.getEquivalenceClass() != -1 && 1871 middleP.getEquivalenceClass() != outerEC) 1872 { 1873 continue; 1874 } 1875 1876 int innerTableNumber; 1877 int innerColumnNumber; 1878 1879 BinaryRelationalOperatorNode middleEquals = 1881 (BinaryRelationalOperatorNode) middleP.getAndNode().getLeftOperand(); 1882 ColumnReference mLeftCR = (ColumnReference) middleEquals.getLeftOperand(); 1883 ColumnReference mRightCR = (ColumnReference) middleEquals.getRightOperand(); 1884 1885 1888 if (mLeftCR.getTableNumber() == middleTableNumber) 1889 { 1890 if (mLeftCR.getColumnNumber() != middleColumnNumber) 1891 { 1892 continue; 1893 } 1894 innerTableNumber = mRightCR.getTableNumber(); 1895 innerColumnNumber = mRightCR.getColumnNumber(); 1896 } 1897 else 1898 { 1899 if (mRightCR.getColumnNumber() != middleColumnNumber) 1900 { 1901 continue; 1902 } 1903 innerTableNumber = mLeftCR.getTableNumber(); 1904 innerColumnNumber = mLeftCR.getColumnNumber(); 1905 } 1906 1907 if (outerTableNumber == innerTableNumber && 1909 outerColumnNumber == innerColumnNumber) 1910 { 1911 continue; 1912 } 1913 1914 middleP.setEquivalenceClass(outerEC); 1916 1917 1923 1924 int newTableNumber; 1925 int newColumnNumber; 1926 Predicate innerP = null; 1927 PredicateList innerJCL = joinClauses[innerTableNumber]; 1928 int innerIndex = 0; 1929 for ( ; innerIndex < innerJCL.size(); innerIndex++) 1930 { 1931 innerP = (Predicate) innerJCL.elementAt(innerIndex); 1932 1933 if (innerP.getEquivalenceClass() != -1 && 1935 innerP.getEquivalenceClass() != outerEC) 1936 { 1937 continue; 1938 } 1939 1940 1944 1945 BinaryRelationalOperatorNode innerEquals = 1947 (BinaryRelationalOperatorNode) innerP.getAndNode().getLeftOperand(); 1948 ColumnReference iLeftCR = (ColumnReference) innerEquals.getLeftOperand(); 1949 ColumnReference iRightCR = (ColumnReference) innerEquals.getRightOperand(); 1950 1951 if (iLeftCR.getTableNumber() == innerTableNumber) 1952 { 1953 if (iLeftCR.getColumnNumber() != innerColumnNumber) 1954 { 1955 continue; 1956 } 1957 newTableNumber = iRightCR.getTableNumber(); 1958 newColumnNumber = iRightCR.getColumnNumber(); 1959 innerCR = iLeftCR; 1960 } 1961 else 1962 { 1963 if (iRightCR.getColumnNumber() != innerColumnNumber) 1964 { 1965 continue; 1966 } 1967 newTableNumber = iLeftCR.getTableNumber(); 1968 newColumnNumber = iLeftCR.getColumnNumber(); 1969 innerCR = iRightCR; 1970 } 1971 1972 if (newTableNumber == outerTableNumber && 1974 newColumnNumber == outerColumnNumber) 1975 { 1976 break; 1977 } 1978 } 1979 1980 if (innerIndex != innerJCL.size()) 1982 { 1983 innerP.setEquivalenceClass(outerEC); 1986 continue; 1987 } 1988 1989 BinaryRelationalOperatorNode newEquals = (BinaryRelationalOperatorNode) 1992 getNodeFactory().getNode( 1993 C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE, 1994 outerCR.getClone(), 1995 innerCR.getClone(), 1996 getContextManager()); 1997 newEquals.bindComparisonOperator(); 1998 1999 ValueNode trueNode = (ValueNode) getNodeFactory().getNode( 2000 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 2001 Boolean.TRUE, 2002 getContextManager()); 2003 AndNode newAnd = (AndNode) getNodeFactory().getNode( 2004 C_NodeTypes.AND_NODE, 2005 newEquals, 2006 trueNode, 2007 getContextManager()); 2008 newAnd.postBindFixup(); 2009 JBitSet tableMap = new JBitSet(numTables); 2011 newAnd.categorize(tableMap, false); 2012 Predicate newPred = (Predicate) getNodeFactory().getNode( 2013 C_NodeTypes.PREDICATE, 2014 newAnd, 2015 tableMap, 2016 getContextManager()); 2017 newPred.setEquivalenceClass(outerEC); 2018 addPredicate(newPred); 2019 2023 if (outerIndex != outerJCL.size() - 1) 2024 { 2025 outerJCL.insertElementAt(newPred, outerIndex + 1); 2026 } 2027 else 2028 { 2029 outerJCL.addElement(newPred); 2030 } 2031 innerJCL.addElement(newPred); 2032 } 2033 } 2034 } 2035 } 2036 2037 2060 void searchClauseTransitiveClosure(int numTables, boolean hashJoinSpecified) 2061 throws StandardException 2062 { 2063 PredicateList equijoinClauses = new PredicateList(); 2064 PredicateList searchClauses = new PredicateList(); 2065 RelationalOperator equalsNode = null; 2066 2067 int size = size(); 2068 for (int index = 0; index < size; index++) 2069 { 2070 Predicate predicate = (Predicate) elementAt(index); 2071 AndNode andNode = predicate.getAndNode(); 2072 2073 if (! (andNode.getLeftOperand() instanceof RelationalOperator)) 2075 { 2076 continue; 2077 } 2078 2079 RelationalOperator operator = (RelationalOperator) andNode.getLeftOperand(); 2080 if (((ValueNode)operator).isBinaryEqualsOperatorNode()) 2082 { 2083 BinaryRelationalOperatorNode equals = (BinaryRelationalOperatorNode) operator; 2084 equalsNode = equals; 2086 ValueNode left = equals.getLeftOperand(); 2087 ValueNode right = equals.getRightOperand(); 2088 if ((left instanceof ColumnReference && right instanceof ColumnReference)) 2089 { 2090 ColumnReference leftCR = (ColumnReference) left; 2091 ColumnReference rightCR = (ColumnReference) right; 2092 if (leftCR.getSourceLevel() == rightCR.getSourceLevel() && 2093 leftCR.getTableNumber() != rightCR.getTableNumber()) 2094 { 2095 equijoinClauses.addElement(predicate); 2096 } 2097 continue; 2098 } 2099 } 2100 2101 if (operator instanceof UnaryComparisonOperatorNode) 2103 { 2104 if (((UnaryComparisonOperatorNode) operator).getOperand() instanceof ColumnReference) 2105 { 2106 searchClauses.addElement(predicate); 2107 } 2108 continue; 2109 } 2110 else if (operator instanceof BinaryComparisonOperatorNode) 2111 { 2112 BinaryComparisonOperatorNode bcon = (BinaryComparisonOperatorNode) operator; 2113 ValueNode left = bcon.getLeftOperand(); 2114 ValueNode right = bcon.getRightOperand(); 2115 2116 if (left instanceof ColumnReference && 2119 (right instanceof ConstantNode || right instanceof ParameterNode)) 2120 { 2121 searchClauses.addElement(predicate); 2122 } 2123 else if (right instanceof ConstantNode && left instanceof ColumnReference) 2124 { 2125 bcon.swapOperands(); 2127 searchClauses.addElement(predicate); 2128 } 2129 continue; 2130 } 2131 } 2132 2133 if (equijoinClauses.size() == 0 || searchClauses.size() == 0) 2135 { 2136 return; 2137 } 2138 2139 2143 for (int scIndex = 0; scIndex < searchClauses.size(); scIndex++) 2144 { 2145 ColumnReference searchCR; 2146 DataValueDescriptor searchODV = null; 2147 RelationalOperator ro = (RelationalOperator) 2148 ((AndNode) 2149 ((Predicate) searchClauses.elementAt(scIndex)).getAndNode()).getLeftOperand(); 2150 2151 if (ro instanceof UnaryComparisonOperatorNode) 2153 { 2154 searchCR = (ColumnReference) ((UnaryComparisonOperatorNode) ro).getOperand(); 2155 } 2156 else 2157 { 2158 searchCR = (ColumnReference) ((BinaryComparisonOperatorNode) ro).getLeftOperand(); 2159 2160 if (((BinaryComparisonOperatorNode) ro).getRightOperand() instanceof ConstantNode) 2162 { 2163 ConstantNode currCN = (ConstantNode) ((BinaryComparisonOperatorNode) ro).getRightOperand(); 2164 searchODV = (DataValueDescriptor) currCN.getValue(); 2165 } 2166 else searchODV = null; 2167 } 2168 int tableNumber = searchCR.getTableNumber(); 2170 int colNumber = searchCR.getColumnNumber(); 2171 2172 int ejcSize = equijoinClauses.size(); 2174 for (int ejcIndex = 0; ejcIndex < ejcSize; ejcIndex++) 2175 { 2176 2183 Predicate predicate = (Predicate) equijoinClauses.elementAt(ejcIndex); 2184 if (predicate.transitiveSearchClauseAdded(ro)) 2185 { 2186 continue; 2187 } 2188 2189 BinaryRelationalOperatorNode equals = (BinaryRelationalOperatorNode) 2190 ((AndNode) 2191 predicate.getAndNode()).getLeftOperand(); 2192 ColumnReference leftCR = (ColumnReference) equals.getLeftOperand(); 2193 ColumnReference rightCR = (ColumnReference) equals.getRightOperand(); 2194 ColumnReference otherCR; 2195 2196 if (leftCR.getTableNumber() == tableNumber && 2197 leftCR.getColumnNumber() == colNumber) 2198 { 2199 otherCR = rightCR; 2200 } 2201 else if (rightCR.getTableNumber() == tableNumber && 2202 rightCR.getColumnNumber() == colNumber) 2203 { 2204 otherCR = leftCR; 2205 } 2206 else 2207 { 2208 continue; 2210 } 2211 2212 2219 predicate.setTransitiveSearchClauseAdded(ro); 2220 2221 boolean match = false; 2222 ColumnReference searchCR2 = null; 2223 RelationalOperator ro2 = null; 2224 int scSize = searchClauses.size(); 2225 for (int scIndex2 = 0; scIndex2 < scSize; scIndex2++) 2226 { 2227 DataValueDescriptor currODV = null; 2228 ro2 = (RelationalOperator) 2229 ((AndNode) 2230 ((Predicate) searchClauses.elementAt(scIndex2)).getAndNode()).getLeftOperand(); 2231 2232 if (ro2 instanceof UnaryComparisonOperatorNode) 2234 { 2235 searchCR2 = (ColumnReference) ((UnaryComparisonOperatorNode) ro2).getOperand(); 2236 } 2237 else 2238 { 2239 searchCR2 = (ColumnReference) ((BinaryComparisonOperatorNode) ro2).getLeftOperand(); 2240 if (((BinaryComparisonOperatorNode) ro2).getRightOperand() instanceof ConstantNode) 2241 { 2242 ConstantNode currCN = (ConstantNode) ((BinaryComparisonOperatorNode) ro2).getRightOperand(); 2243 currODV = (DataValueDescriptor) currCN.getValue(); 2244 } 2245 else currODV = null; 2246 } 2247 2248 2252 if (searchCR2.getTableNumber() == otherCR.getTableNumber() && 2253 searchCR2.getColumnNumber() == otherCR.getColumnNumber() && 2254 ((currODV != null && searchODV != null && currODV.compare(searchODV) == 0) || 2255 (currODV == null && searchODV == null)) && 2256 ro2.getOperator() == ro.getOperator() && 2257 ro2.getClass().getName().equals(ro.getClass().getName())) 2258 { 2259 match = true; 2260 break; 2261 } 2262 } 2263 2264 if (! match) 2266 { 2267 RelationalOperator roClone = ro.getTransitiveSearchClause((ColumnReference) otherCR.getClone()); 2269 2270 2271 if (roClone instanceof BinaryComparisonOperatorNode) 2272 { 2273 ((BinaryComparisonOperatorNode) roClone).bindComparisonOperator(); 2274 } 2275 else 2276 { 2277 ((UnaryComparisonOperatorNode) roClone).bindComparisonOperator(); 2278 } 2279 2280 2281 ValueNode trueNode = (ValueNode) getNodeFactory().getNode( 2282 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 2283 Boolean.TRUE, 2284 getContextManager()); 2285 AndNode newAnd = (AndNode) getNodeFactory().getNode( 2286 C_NodeTypes.AND_NODE, 2287 roClone, 2288 trueNode, 2289 getContextManager()); 2290 newAnd.postBindFixup(); 2291 JBitSet tableMap = new JBitSet(numTables); 2293 newAnd.categorize(tableMap, false); 2294 Predicate newPred = (Predicate) getNodeFactory().getNode( 2295 C_NodeTypes.PREDICATE, 2296 newAnd, 2297 tableMap, 2298 getContextManager()); 2299 addPredicate(newPred); 2300 searchClauses.addElement(newPred); 2301 } 2302 } 2303 } 2304 2305 2309 if (hashJoinSpecified) 2310 { 2311 return; 2312 } 2313 2314 2317 for (int index = size() - 1; index >= 0; index--) 2318 { 2319 Predicate predicate = (Predicate) elementAt(index); 2320 2321 if (predicate.transitiveSearchClauseAdded(equalsNode)) 2322 { 2323 removeElementAt(index); 2324 } 2325 } 2326 } 2327 2328 2334 void removeRedundantPredicates() 2335 { 2336 2339 int outer = size() - 1; 2340 while (outer >= 0) 2341 { 2342 Predicate predicate = (Predicate) elementAt(outer); 2343 int equivalenceClass = predicate.getEquivalenceClass(); 2344 2345 if (equivalenceClass == -1) 2346 { 2347 outer--; 2348 continue; 2349 } 2350 2351 for (int inner = outer - 1; inner >= 0; inner--) 2353 { 2354 Predicate innerPredicate = (Predicate) elementAt(inner); 2355 if (innerPredicate.getEquivalenceClass() == equivalenceClass) 2356 { 2357 2365 if (innerPredicate.isStartKey()) 2366 { 2367 predicate.markStartKey(); 2368 } 2369 if (innerPredicate.isStopKey()) 2370 { 2371 predicate.markStopKey(); 2372 } 2373 if (innerPredicate.isStartKey() || innerPredicate.isStopKey()) 2374 { 2375 if (innerPredicate.isQualifier()) 2376 { 2377 if (!predicate.isQualifier()) 2387 { 2388 predicate.markQualifier(); 2389 numberOfQualifiers++; 2390 } 2391 } 2392 } 2393 2398 if (innerPredicate.isQualifier()) 2399 { 2400 numberOfQualifiers--; 2401 } 2402 removeElementAt(inner); 2403 outer--; 2404 } 2405 } 2406 2407 outer--; 2408 } 2409 } 2410 2411 2416 public void transferPredicates(OptimizablePredicateList otherList, 2417 JBitSet referencedTableMap, 2418 Optimizable table) 2419 throws StandardException 2420 { 2421 Predicate predicate; 2422 PredicateList theOtherList = (PredicateList) otherList; 2423 2424 2427 for (int index = size() - 1; index >= 0; index--) 2428 { 2429 predicate = (Predicate) elementAt(index); 2430 2431 if (SanityManager.DEBUG) 2432 { 2433 if (referencedTableMap.size() != predicate.getReferencedSet().size()) 2434 { 2435 SanityManager.THROWASSERT( 2436 "referencedTableMap.size() (" + referencedTableMap.size() + 2437 ") does not equal predicate.getReferencedSet().size() (" + 2438 predicate.getReferencedSet().size()); 2439 } 2440 } 2441 2442 if (referencedTableMap.contains(predicate.getReferencedSet())) 2443 { 2444 if (predicate.isStartKey()) 2446 numberOfStartPredicates--; 2447 if (predicate.isStopKey()) 2448 numberOfStopPredicates--; 2449 if (predicate.isQualifier()) 2450 numberOfQualifiers--; 2451 2452 2455 predicate.clearScanFlags(); 2456 theOtherList.addPredicate(predicate); 2458 removeElementAt(index); 2459 } 2460 } 2461 2462 AccessPath ap = table.getTrulyTheBestAccessPath(); 2464 theOtherList.orderUsefulPredicates( 2465 table, 2466 ap.getConglomerateDescriptor(), 2467 false, 2468 ap.getNonMatchingIndexScan(), 2469 ap.getCoveringIndexScan()); 2470 2471 theOtherList.countScanFlags(); 2473 } 2474 2475 2480 public void transferAllPredicates(OptimizablePredicateList otherList) 2481 throws StandardException 2482 { 2483 PredicateList theOtherList = (PredicateList) otherList; 2484 2485 int size = size(); 2486 for (int index = 0; index < size; index++) 2487 { 2488 Predicate predicate = (Predicate) elementAt(index); 2489 2490 2494 predicate.clearScanFlags(); 2495 2496 theOtherList.addPredicate(predicate); 2498 } 2499 2500 removeAllElements(); 2502 2503 2507 numberOfStartPredicates = 0; 2508 numberOfStopPredicates = 0; 2509 numberOfQualifiers= 0; 2510 } 2511 2512 2517 public void copyPredicatesToOtherList(OptimizablePredicateList otherList) 2518 throws StandardException 2519 { 2520 for (int i = 0; i < size(); i++) 2521 { 2522 otherList.addOptPredicate(getOptPredicate(i)); 2523 } 2524 } 2525 2526 2529 public boolean isRedundantPredicate(int predNum) 2530 { 2531 Predicate pred = (Predicate) elementAt(predNum); 2532 if (pred.getEquivalenceClass() == -1) 2533 { 2534 return false; 2535 } 2536 for (int index = 0; index < predNum; index++) 2537 { 2538 if ( ((Predicate) elementAt(index)).getEquivalenceClass() == pred.getEquivalenceClass()) 2539 { 2540 return true; 2541 } 2542 } 2543 return false; 2544 } 2545 2546 2551 public void setPredicatesAndProperties(OptimizablePredicateList otherList) 2552 throws StandardException 2553 { 2554 PredicateList theOtherList = (PredicateList) otherList; 2555 2556 theOtherList.removeAllElements(); 2557 2558 for (int i = 0; i < size(); i++) 2559 { 2560 theOtherList.addOptPredicate(getOptPredicate(i)); 2561 } 2562 2563 theOtherList.numberOfStartPredicates = numberOfStartPredicates; 2564 theOtherList.numberOfStopPredicates = numberOfStopPredicates; 2565 theOtherList.numberOfQualifiers = numberOfQualifiers; 2566 } 2567 2568 2569 public int startOperator(Optimizable optTable) 2570 { 2571 int startOperator; 2572 2573 2578 startOperator = ScanController.GT; 2579 2580 int size = size(); 2581 2584 for (int index = size - 1; index >= 0; index--) 2585 { 2586 Predicate pred = ((Predicate) elementAt(index)); 2587 2588 if ( ! pred.isStartKey() ) 2589 continue; 2590 2591 startOperator = pred.getStartOperator(optTable); 2592 break; 2593 } 2594 return startOperator; 2595 } 2596 2597 2602 public void generateStopKey(ExpressionClassBuilderInterface acbi, 2603 MethodBuilder mb, 2604 Optimizable optTable) 2605 throws StandardException 2606 { 2607 ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi; 2608 2609 2626 2627 if (numberOfStopPredicates != 0) 2628 { 2629 2630 MethodBuilder exprFun = acb.newExprFun(); 2631 2632 2633 LocalField rowField = 2634 generateIndexableRow(acb, numberOfStopPredicates); 2635 2636 int colNum = 0; 2637 int size = size(); 2638 for (int index = 0; index < size; index++) 2639 { 2640 Predicate pred = ((Predicate) elementAt(index)); 2641 2642 if ( ! pred.isStopKey() ) 2643 continue; 2644 2645 generateSetColumn(acb, exprFun, colNum, 2646 pred, optTable, rowField, false); 2647 2648 colNum++; 2649 } 2650 2651 if (SanityManager.DEBUG) 2652 { 2653 SanityManager.ASSERT(colNum == numberOfStopPredicates, 2654 "Number of stop predicates does not match"); 2655 } 2656 2657 finishKey(acb, mb, exprFun, rowField); 2658 return; 2659 } 2660 2661 mb.pushNull(ClassName.GeneratedMethod); 2662 } 2663 2664 2665 public int stopOperator(Optimizable optTable) 2666 { 2667 int stopOperator; 2668 2669 2674 stopOperator = ScanController.GT; 2675 2676 int size = size(); 2677 2680 for (int index = size - 1; index >= 0; index--) 2681 { 2682 Predicate pred = ((Predicate) elementAt(index)); 2683 2684 if ( ! pred.isStopKey() ) 2685 continue; 2686 2687 stopOperator = pred.getStopOperator(optTable); 2688 break; 2689 } 2690 return stopOperator; 2691 } 2692 2693 private void generateSingleQualifierCode( 2694 MethodBuilder consMB, 2695 Optimizable optTable, 2696 boolean absolute, 2697 ExpressionClassBuilder acb, 2698 RelationalOperator or_node, 2699 LocalField qualField, 2700 int array_idx_1, 2701 int array_idx_2) 2702 throws StandardException 2703 { 2704 consMB.getField(qualField); 2706 consMB.pushThis(); 2708 consMB.callMethod( 2709 VMOpcode.INVOKEVIRTUAL, 2710 acb.getBaseClassName(), 2711 "getExecutionFactory", ExecutionFactory.MODULE, 0); 2712 2713 if (absolute) 2715 or_node.generateAbsoluteColumnId(consMB, optTable); 2716 else 2717 or_node.generateRelativeColumnId(consMB, optTable); 2718 2719 or_node.generateOperator(consMB, optTable); 2721 2722 or_node.generateQualMethod(acb, consMB, optTable); 2724 2725 acb.pushThisAsActivation(consMB); 2727 2728 or_node.generateOrderedNulls(consMB); 2730 2731 2732 2742 or_node.generateNegate(consMB, optTable); 2743 2744 2745 or_node.generateNegate(consMB, optTable); 2746 2747 2748 consMB.push(or_node.getOrderableVariantType(optTable)); 2749 2750 consMB.callMethod( 2751 VMOpcode.INVOKEINTERFACE, 2752 ExecutionFactory.MODULE, 2753 "getQualifier", ClassName.Qualifier, 8); 2754 2755 2757 consMB.push(array_idx_1); consMB.push(array_idx_2); 2760 consMB.callMethod( 2761 VMOpcode.INVOKESTATIC, 2762 acb.getBaseClassName(), 2763 "setQualifier", "void", 4); 2764 } 2765 2766 2771 public void generateQualifiers( 2772 ExpressionClassBuilderInterface acbi, 2773 MethodBuilder mb, 2774 Optimizable optTable, 2775 boolean absolute) 2776 throws StandardException 2777 { 2778 ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi; 2779 2780 String retvalType = ClassName.Qualifier + "[][]"; 2781 MethodBuilder consMB = acb.getConstructor(); 2782 MethodBuilder executeMB = acb.getExecuteMethod(); 2783 2784 2785 LocalField qualField = 2786 acb.newFieldDeclaration(Modifier.PRIVATE, retvalType); 2787 2788 2789 2802 2803 2810 executeMB.getField(qualField); executeMB.callMethod( 2813 VMOpcode.INVOKESTATIC, 2814 acb.getBaseClassName(), "reinitializeQualifiers", "void", 1); 2815 2816 2821 if (numberOfQualifiers != 0) 2822 { 2823 if (SanityManager.DEBUG) 2824 { 2825 if (numberOfQualifiers > size()) 2826 { 2827 SanityManager.THROWASSERT( 2828 "numberOfQualifiers(" + numberOfQualifiers + 2829 ") > size(" + size() + ")." + ":" + this.hashCode()); 2830 } 2831 } 2832 2833 int num_of_or_conjunctions = 0; 2836 for (int i = 0; i < numberOfQualifiers; i++) 2837 { 2838 if (((Predicate) elementAt(i)).isOrList()) 2839 { 2840 num_of_or_conjunctions++; 2841 } 2842 } 2843 2844 2845 2846 consMB.pushNewArray( 2847 ClassName.Qualifier + "[]", (int) num_of_or_conjunctions + 1); 2848 consMB.setField(qualField); 2849 2850 2853 consMB.getField(qualField); consMB.push((int) 0); consMB.push((int) numberOfQualifiers - num_of_or_conjunctions); 2857 consMB.callMethod( 2858 VMOpcode.INVOKESTATIC, 2859 acb.getBaseClassName(), 2860 "allocateQualArray", "void", 3); 2861 } 2862 2863 2875 if (numberOfQualifiers > 0) 2876 { 2877 orderQualifiers(); 2878 } 2879 2880 2881 2882 int qualNum = 0; 2884 int size = size(); 2885 boolean gotOrQualifier = false; 2886 2887 for (int index = 0; index < size; index++) 2888 { 2889 2890 Predicate pred = ((Predicate) elementAt(index)); 2891 2892 if (!pred.isQualifier()) 2893 { 2894 continue; 2895 } 2896 else if (pred.isOrList()) 2897 { 2898 gotOrQualifier = true; 2899 2900 break; 2902 } 2903 else 2904 { 2905 generateSingleQualifierCode( 2906 consMB, 2907 optTable, 2908 absolute, 2909 acb, 2910 pred.getRelop(), 2911 qualField, 2912 0, 2913 qualNum); 2914 2915 qualNum++; 2916 } 2917 } 2918 2919 if (gotOrQualifier) 2920 { 2921 2922 int and_idx = 1; 2934 2935 2938 for (int index = qualNum; index < size; index++, and_idx++) 2939 { 2940 2941 Predicate pred = ((Predicate) elementAt(index)); 2942 2943 if (SanityManager.DEBUG) 2944 { 2945 SanityManager.ASSERT(pred.isOrList()); 2946 } 2947 2948 ArrayList a_list = new ArrayList (); 2953 2954 QueryTreeNode node = pred.getAndNode().getLeftOperand(); 2955 2956 while (node instanceof OrNode) 2957 { 2958 OrNode or_node = (OrNode) node; 2959 2960 if (or_node.getLeftOperand() instanceof RelationalOperator) 2963 { 2964 a_list.add(or_node.getLeftOperand()); 2965 } 2966 2967 node = or_node.getRightOperand(); 2969 } 2970 2971 2974 consMB.getField(qualField); consMB.push((int) and_idx); consMB.push((int) a_list.size()); 2978 consMB.callMethod( 2979 VMOpcode.INVOKESTATIC, 2980 acb.getBaseClassName(), 2981 "allocateQualArray", "void", 3); 2982 2983 2984 for (int i = 0; i < a_list.size(); i++) 2986 { 2987 generateSingleQualifierCode( 2988 consMB, 2989 optTable, 2990 absolute, 2991 acb, 2992 (RelationalOperator) a_list.get(i), 2993 qualField, 2994 and_idx, 2995 i); 2996 2997 } 2998 2999 qualNum++; 3000 } 3001 3002 } 3003 3004 if (SanityManager.DEBUG) 3005 { 3006 SanityManager.ASSERT(qualNum == numberOfQualifiers, 3007 qualNum + " Qualifiers found, " + 3008 numberOfQualifiers + " expected."); 3009 } 3010 3011 3015 mb.getField(qualField); 3016 } 3017 3018 3019 3031 private static final int QUALIFIER_ORDER_EQUALS = 0; 3032 private static final int QUALIFIER_ORDER_OTHER_RELOP = 1; 3033 private static final int QUALIFIER_ORDER_NOT_EQUALS = 2; 3034 private static final int QUALIFIER_ORDER_NON_QUAL = 3; 3035 private static final int QUALIFIER_ORDER_OR_CLAUSE = 4; 3036 private static final int QUALIFIER_NUM_CATEGORIES = 5; 3037 private void orderQualifiers() 3038 { 3039 PredicateList[] sortList = new PredicateList[QUALIFIER_NUM_CATEGORIES]; 3048 3049 for (int i = sortList.length - 1; i >= 0; i--) 3050 sortList[i] = new PredicateList(); 3051 3052 int predIndex; 3053 int size = size(); 3054 for (predIndex = 0; predIndex < size; predIndex++) 3055 { 3056 Predicate pred = (Predicate) elementAt(predIndex); 3057 3058 if (! pred.isQualifier()) 3059 { 3060 sortList[QUALIFIER_ORDER_NON_QUAL].addElement(pred); 3061 continue; 3062 } 3063 3064 AndNode node = pred.getAndNode(); 3065 3066 if (!(node.getLeftOperand() instanceof OrNode)) 3067 { 3068 RelationalOperator relop = 3069 (RelationalOperator) node.getLeftOperand(); 3070 3071 int op = relop.getOperator(); 3072 3073 switch (op) 3074 { 3075 case RelationalOperator.EQUALS_RELOP: 3076 case RelationalOperator.IS_NULL_RELOP: 3077 sortList[QUALIFIER_ORDER_EQUALS].addElement(pred); 3078 break; 3079 3080 case RelationalOperator.NOT_EQUALS_RELOP: 3081 case RelationalOperator.IS_NOT_NULL_RELOP: 3082 sortList[QUALIFIER_ORDER_NOT_EQUALS].addElement(pred); 3083 break; 3084 3085 default: 3086 sortList[QUALIFIER_ORDER_OTHER_RELOP].addElement(pred); 3087 } 3088 } 3089 else 3090 { 3091 sortList[QUALIFIER_ORDER_OR_CLAUSE].addElement(pred); 3092 } 3093 } 3094 3095 3096 predIndex = 0; 3097 3098 for (int index = 0; index < QUALIFIER_NUM_CATEGORIES; index++) 3099 { 3100 for (int items = 0; items < sortList[index].size(); items++) 3101 { 3102 setElementAt(sortList[index].elementAt(items), predIndex++); 3103 } 3104 } 3105 } 3106 3107 3112 public void generateStartKey(ExpressionClassBuilderInterface acbi, 3113 MethodBuilder mb, 3114 Optimizable optTable) 3115 throws StandardException 3116 { 3117 ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi; 3118 3119 3136 3137 if (numberOfStartPredicates != 0) 3138 { 3139 3140 MethodBuilder exprFun = acb.newExprFun(); 3141 3142 3143 LocalField rowField = generateIndexableRow(acb, numberOfStartPredicates); 3144 3145 int colNum = 0; 3146 int size = size(); 3147 for (int index = 0; index < size; index++) 3148 { 3149 Predicate pred = ((Predicate) elementAt(index)); 3150 3151 if ( ! pred.isStartKey() ) 3152 continue; 3153 3154 generateSetColumn(acb, exprFun, colNum, 3155 pred, optTable, rowField, true); 3156 3157 colNum++; 3158 } 3159 3160 if (SanityManager.DEBUG) 3161 { 3162 SanityManager.ASSERT(colNum == numberOfStartPredicates, 3163 "Number of start predicates does not match"); 3164 } 3165 3166 finishKey(acb, mb, exprFun, rowField); 3167 return; 3168 } 3169 3170 mb.pushNull(ClassName.GeneratedMethod); 3171 } 3172 3173 3178 public boolean sameStartStopPosition() 3179 throws StandardException 3180 { 3181 3185 if (numberOfStartPredicates != numberOfStopPredicates) 3186 { 3187 return false; 3188 } 3189 3190 3194 int size = size(); 3195 for (int index = 0; index < size; index++) 3196 { 3197 Predicate pred = ((Predicate) elementAt(index)); 3198 3199 if ( (pred.isStartKey() && (! pred.isStopKey())) || 3200 (pred.isStopKey() && (! pred.isStartKey()))) 3201 { 3202 return false; 3203 } 3204 3206 if (pred.getAndNode().getLeftOperand() instanceof InListOperatorNode) 3207 return false; 3208 } 3209 3210 return true; 3211 } 3212 3213 3221 private LocalField generateIndexableRow(ExpressionClassBuilder acb, int numberOfColumns) 3222 { 3223 MethodBuilder mb = acb.getConstructor(); 3224 3228 acb.pushGetExecutionFactoryExpression(mb); mb.push(numberOfColumns); 3230 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecutionFactory, "getIndexableRow", ClassName.ExecIndexRow, 1); 3231 3232 3237 LocalField field = 3238 acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecIndexRow); 3239 3240 mb.setField(field); 3241 3242 return field; 3243 } 3244 3245 3260 private void generateSetColumn(ExpressionClassBuilder acb, 3261 MethodBuilder exprFun, 3262 int columnNumber, 3263 Predicate pred, 3264 Optimizable optTable, 3265 LocalField rowField, 3266 boolean isStartKey) 3267 throws StandardException 3268 { 3269 MethodBuilder mb; 3270 3271 3275 boolean withKnownConstant = false; 3276 if (pred.compareWithKnownConstant(optTable, false)) 3277 { 3278 withKnownConstant = true; 3279 mb = acb.getConstructor(); 3280 } 3281 else 3282 { 3283 mb = exprFun; 3284 } 3285 3286 int[] baseColumns = optTable.getTrulyTheBestAccessPath(). 3287 getConglomerateDescriptor(). 3288 getIndexDescriptor().baseColumnPositions(); 3289 boolean[] isAscending = optTable.getTrulyTheBestAccessPath(). 3290 getConglomerateDescriptor(). 3291 getIndexDescriptor().isAscending(); 3292 boolean isIn = pred.getAndNode().getLeftOperand() instanceof InListOperatorNode; 3293 3294 3301 mb.getField(rowField); 3302 mb.push(columnNumber + 1); 3303 3304 if (isIn) 3306 { 3307 InListOperatorNode inNode = (InListOperatorNode) pred.getAndNode().getLeftOperand(); 3308 inNode.generateStartStopKey(isAscending[columnNumber], isStartKey, acb, mb); 3309 } 3310 else 3311 pred.generateExpressionOperand(optTable, baseColumns[columnNumber], acb, mb); 3312 3313 mb.upCast(ClassName.DataValueDescriptor); 3314 3315 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2); 3316 3317 3318 if (!isIn) 3319 { 3320 RelationalOperator relop = pred.getRelop(); 3321 boolean setOrderedNulls = relop.orderedNulls(); 3322 3323 3333 if ((! setOrderedNulls) && 3334 ! relop.getColumnOperand(optTable).getTypeServices().isNullable()) 3335 { 3336 if (withKnownConstant) 3337 setOrderedNulls = true; 3338 else 3339 { 3340 ValueNode keyExp = 3341 relop.getExpressionOperand( 3342 optTable.getTableNumber(), 3343 baseColumns[columnNumber], 3344 (FromTable)optTable); 3345 3346 if (keyExp instanceof ColumnReference) 3347 setOrderedNulls = 3348 ! ((ColumnReference) keyExp).getTypeServices().isNullable(); 3349 } 3350 } 3351 if (setOrderedNulls) 3352 { 3353 mb.getField(rowField); 3354 mb.push(columnNumber); 3355 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecIndexRow, "orderedNulls", "void", 1); 3356 } 3357 } 3358 } 3359 3360 3367 private void finishKey(ExpressionClassBuilder acb, 3368 MethodBuilder mb, 3369 MethodBuilder exprFun, 3370 LocalField rowField) 3371 { 3372 3373 exprFun.getField(rowField); 3374 exprFun.methodReturn(); 3375 3376 exprFun.complete(); 3377 3378 3382 acb.pushMethodReference(mb, exprFun); 3383 } 3384 3385 3386 boolean constantColumn(ColumnReference colRef) 3387 { 3388 boolean retval = false; 3389 3390 3393 int size = size(); 3394 for (int index = 0; index < size; index++) 3395 { 3396 Predicate pred = (Predicate) elementAt(index); 3397 RelationalOperator relop = pred.getRelop(); 3398 3399 if (relop != null) 3400 { 3401 if (relop.getOperator() == RelationalOperator.EQUALS_RELOP) 3402 { 3403 ValueNode exprOp = relop.getOperand( 3404 colRef, 3405 pred.getReferencedSet().size(), 3406 true 3407 ); 3408 3409 if (exprOp != null) 3410 { 3411 if (exprOp.isConstantExpression()) 3412 { 3413 retval = true; 3414 break; 3415 } 3416 } 3417 } 3418 else if (relop.getOperator() == 3419 RelationalOperator.IS_NULL_RELOP) 3420 { 3421 ColumnReference columnOp = 3422 (ColumnReference)relop.getOperand( 3423 colRef, 3424 pred.getReferencedSet().size(), 3425 false 3426 ); 3427 3428 if (columnOp != null) 3429 { 3430 retval = true; 3431 } 3432 } 3433 } 3434 } 3435 3436 return retval; 3437 } 3438 3439 3442 public double selectivity(Optimizable optTable) 3443 throws StandardException 3444 { 3445 TableDescriptor td = optTable.getTableDescriptor(); 3446 ConglomerateDescriptor[] conglomerates = td.getConglomerateDescriptors(); 3447 3448 int numPredicates = size(); 3449 int numConglomerates = conglomerates.length; 3450 3451 if (numConglomerates == 1) 3452 return -1.0d; 3454 if (numPredicates == 0) 3455 return -1.0d; 3457 boolean nothingYet = true; 3458 3459 3463 PredicateList workingPredicates = new PredicateList(); 3464 3465 for (int i = 0; i < numPredicates; i++) 3466 { 3467 if (isRedundantPredicate(i)) 3468 continue; 3469 3470 3471 workingPredicates.addOptPredicate((Predicate)elementAt(i)); 3472 } 3473 3474 int numWorkingPredicates = workingPredicates.size(); 3475 3476 3503 PredicateWrapperList[] 3504 predsForConglomerates = new PredicateWrapperList[numConglomerates]; 3505 3506 for (int i = 0; i < numConglomerates; i++) 3507 { 3508 ConglomerateDescriptor cd = conglomerates[i]; 3509 3510 if (!cd.isIndex()) 3511 continue; 3512 3513 if (!td.statisticsExist(cd)) 3514 continue; 3515 3516 int[] baseColumnList = 3517 cd.getIndexDescriptor().baseColumnPositions(); 3518 3519 for (int j = 0; j < numWorkingPredicates; j++) 3520 { 3521 Predicate pred = (Predicate)workingPredicates.elementAt(j); 3522 3523 int ip = pred.hasEqualOnColumnList(baseColumnList, 3524 optTable); 3525 3526 if (ip < 0) 3527 continue; 3529 nothingYet = false; 3530 if (predsForConglomerates[i] == null) 3531 { 3532 predsForConglomerates[i] = new PredicateWrapperList(numWorkingPredicates); 3533 } 3534 PredicateWrapper newpw = new PredicateWrapper(ip, pred, j); 3535 predsForConglomerates[i].insert(newpw); 3536 } } 3539 if (nothingYet) 3540 { 3541 return -1.0; 3542 } 3543 3544 3552 3553 int maxOverlap = -1; 3554 for (int i = 0; i < numConglomerates; i++) 3555 { 3556 if (predsForConglomerates[i] == null) 3557 continue; 3558 3559 predsForConglomerates[i].retainLeadingContiguous(); 3560 } 3562 3563 calculateWeight(predsForConglomerates, numWorkingPredicates); 3564 3565 3572 Vector statistics = new Vector (numWorkingPredicates); 3573 3574 double selectivity = 1.0; 3575 3576 Vector maxPreds = new Vector (); 3577 3578 while (true) 3579 { 3580 maxPreds.removeAllElements(); 3581 int conglomIndex = chooseLongestMatch(predsForConglomerates, 3582 maxPreds, numWorkingPredicates); 3583 3584 if (conglomIndex == -1) 3585 break; 3587 selectivity *= 3588 td.selectivityForConglomerate(conglomerates[conglomIndex], maxPreds.size()); 3589 3590 for (int i = 0; i < maxPreds.size(); i++) 3591 { 3592 3595 Predicate p =(Predicate) maxPreds.elementAt(i); 3596 workingPredicates.removeOptPredicate(p); 3597 } 3598 3599 if (workingPredicates.size() == 0) 3600 break; 3601 } 3602 3603 if (workingPredicates.size() != 0) 3604 { 3605 selectivity *= workingPredicates.selectivityNoStatistics(optTable); 3606 } 3607 3608 return selectivity; 3609 } 3610 3611 3616 private void calculateWeight(PredicateWrapperList[] pwList, int numUsefulPredicates) 3617 { 3618 int[] s = new int[numUsefulPredicates]; 3619 3620 for (int i = 0; i < pwList.length; i++) 3621 { 3622 if (pwList[i] == null) 3623 continue; 3624 3625 for (int j = 0; j < pwList[i].size(); j++) 3626 { 3627 s[pwList[i].elementAt(j).getPredicateID()] += 3628 (numUsefulPredicates - j); 3629 } 3630 } 3631 3632 for (int i = 0; i < pwList.length; i++) 3633 { 3634 int w = 0; 3635 3636 if (pwList[i] == null) 3637 continue; 3638 3639 for (int j = 0; j < pwList[i].size(); j++) 3640 { 3641 w += s[pwList[i].elementAt(j).getPredicateID()]; 3642 } 3643 pwList[i].setWeight(w); 3644 } 3645 } 3646 3650 private int chooseLongestMatch(PredicateWrapperList[] predArray, Vector ret, 3651 int numWorkingPredicates) 3652 { 3653 int max = 0, maxWeight = 0; 3654 int position = -1; 3655 int weight; 3656 3657 for (int i = 0; i < predArray.length; i++) 3658 { 3659 if (predArray[i] == null) 3660 continue; 3661 3662 if (predArray[i].uniqueSize() == 0) 3663 continue; 3664 3665 if (predArray[i].uniqueSize() > max) 3666 { 3667 max = predArray[i].uniqueSize(); 3668 position = i; 3669 maxWeight = predArray[i].getWeight(); 3670 } 3671 3672 if (predArray[i].uniqueSize() == max) 3673 { 3674 3677 if (predArray[i].getWeight() > maxWeight) 3678 continue; 3679 3680 position = i; 3681 max = predArray[i].uniqueSize(); 3682 maxWeight = predArray[i].getWeight(); 3683 } 3684 } 3685 3686 if (position == -1) 3687 return -1; 3688 3689 3695 PredicateWrapperList pwl = predArray[position]; 3696 Vector uniquepreds = pwl.createLeadingUnique(); 3697 3698 3702 for (int i = 0; i < uniquepreds.size(); i++) 3703 { 3704 Predicate p = 3705 ((PredicateWrapper)uniquepreds.elementAt(i)).getPredicate(); 3706 ret.addElement(p); 3707 for (int j = 0; j < predArray.length; j++) 3708 { 3709 if (predArray[j] == null) 3710 continue; 3711 3712 pwl = predArray[j]; 3713 3717 pwl.removeElement(p); 3718 } 3719 } 3720 3721 3724 for (int i = 0; i < predArray.length; i++) 3725 { 3726 if (predArray[i] == null) 3727 continue; 3728 predArray[i].retainLeadingContiguous(); 3729 } 3730 3731 3732 calculateWeight(predArray, numWorkingPredicates); 3733 return position; 3734 } 3735 3736 3739 private double selectivityNoStatistics(Optimizable optTable) 3740 throws StandardException 3741 { 3742 double selectivity = 1.0; 3743 3744 for (int i = 0; i < size(); i++) 3745 { 3746 OptimizablePredicate pred = (OptimizablePredicate)elementAt(i); 3747 selectivity *= pred.selectivity((Optimizable)optTable); 3748 } 3749 3750 return selectivity; 3751 } 3752 3753 3762 private class PredicateWrapper 3763 { 3764 int indexPosition; 3765 Predicate pred; 3766 int predicateID; 3767 3768 PredicateWrapper(int ip, Predicate p, int predicateID) 3769 { 3770 this.indexPosition = ip; 3771 this.pred = p; 3772 this.predicateID = predicateID; 3773 } 3774 3775 int getIndexPosition() { return indexPosition; } 3776 Predicate getPredicate() { return pred; } 3777 int getPredicateID() { return predicateID; } 3778 3779 3782 boolean before(PredicateWrapper other) 3783 { 3784 return (indexPosition < other.getIndexPosition()); 3785 } 3786 3787 3790 boolean contiguous(PredicateWrapper other) 3791 { 3792 int otherIP = other.getIndexPosition(); 3793 return ((indexPosition == otherIP) || (indexPosition - otherIP == 1) 3794 || (indexPosition - otherIP == -1)); 3795 } 3796 3797 } 3798 3799 3801 private class PredicateWrapperList 3802 { 3803 Vector pwList; 3804 int numPreds; 3805 int numDuplicates; 3806 int weight; 3807 3808 PredicateWrapperList(int maxValue) 3809 { 3810 pwList = new Vector (maxValue); 3811 } 3812 3813 void removeElement(PredicateWrapper pw) 3814 { 3815 int index = pwList.indexOf(pw); 3816 if (index >= 0) 3817 removeElementAt(index); 3818 } 3819 3820 void removeElement(Predicate p) 3821 { 3822 for (int i = numPreds - 1; i >= 0; i--) 3823 { 3824 Predicate predOnList = elementAt(i).getPredicate(); 3825 if (predOnList == p) removeElementAt(i); 3827 } 3828 } 3829 3830 void removeElementAt(int index) 3831 { 3832 if (index < numPreds - 1) 3833 { 3834 PredicateWrapper nextPW = elementAt(index+1); 3835 if (nextPW.getIndexPosition() == index) 3836 numDuplicates--; 3837 } 3838 pwList.removeElementAt(index); 3839 numPreds--; 3840 } 3841 3842 PredicateWrapper elementAt(int i) 3843 { 3844 return (PredicateWrapper)pwList.elementAt(i); 3845 } 3846 3847 void insert(PredicateWrapper pw) 3848 { 3849 int i; 3850 for (i = 0; i < pwList.size(); i++) 3851 { 3852 if (pw.getIndexPosition() == elementAt(i).getIndexPosition()) 3853 numDuplicates++; 3854 3855 if (pw.before(elementAt(i))) 3856 break; 3857 } 3858 numPreds++; 3859 pwList.insertElementAt(pw, i); 3860 } 3861 3862 int size() 3863 { 3864 return numPreds; 3865 } 3866 3867 3870 int uniqueSize() 3871 { 3872 if (numPreds > 0) 3873 return numPreds - numDuplicates; 3874 return 0; 3875 } 3876 3877 3880 void retainLeadingContiguous() 3881 { 3882 if (pwList == null) 3883 return; 3884 3885 if (pwList.size() == 0) 3886 return; 3887 3888 if (elementAt(0).getIndexPosition() != 0) 3889 { 3890 pwList.removeAllElements(); 3891 numPreds = numDuplicates = 0; 3892 return; 3893 } 3894 3895 int j; 3896 for (j = 0; j < numPreds - 1; j++) 3897 { 3898 if (!(elementAt(j).contiguous(elementAt(j+1)))) 3899 break; 3900 } 3901 3902 3909 3910 for (int k = numPreds - 1; k > j; k--) 3911 { 3912 if (elementAt(k).getIndexPosition() == 3913 elementAt(k-1).getIndexPosition()) 3914 numDuplicates--; 3915 pwList.removeElementAt(k); 3916 } 3917 numPreds = j + 1; 3918 } 3919 3920 3926 Vector createLeadingUnique() 3927 { 3928 Vector scratch = new Vector (); 3929 3930 if (numPreds == 0) 3931 return null; 3932 3933 int lastIndexPosition = elementAt(0).getIndexPosition(); 3934 3935 if (lastIndexPosition != 0) 3936 return null; 3937 3938 scratch.addElement(elementAt(0)); 3940 for (int i = 1; i < numPreds; i++) 3941 { 3942 if (elementAt(i).getIndexPosition() == lastIndexPosition) 3943 continue; 3944 lastIndexPosition = elementAt(i).getIndexPosition(); 3945 scratch.addElement(elementAt(i)); 3946 } 3947 return scratch; 3948 } 3949 3950 void setWeight(int weight) 3951 { 3952 this.weight = weight; 3953 } 3954 3955 int getWeight() 3956 { 3957 return weight; 3958 } 3959 } 3960} 3961 | Popular Tags |