1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.catalog.IndexDescriptor; 25 import org.apache.derby.iapi.util.StringUtil; 26 27 import org.apache.derby.iapi.reference.ClassName; 28 import org.apache.derby.iapi.reference.SQLState; 29 30 import org.apache.derby.iapi.services.io.FormatableBitSet; 31 import org.apache.derby.iapi.services.io.FormatableArrayHolder; 32 import org.apache.derby.iapi.services.io.FormatableIntHolder; 33 import org.apache.derby.iapi.util.JBitSet; 34 import org.apache.derby.iapi.util.ReuseFactory; 35 import org.apache.derby.iapi.services.classfile.VMOpcode; 36 37 import org.apache.derby.iapi.services.compiler.MethodBuilder; 38 import org.apache.derby.iapi.services.property.PropertyUtil; 39 import org.apache.derby.iapi.services.sanity.SanityManager; 40 41 import org.apache.derby.iapi.error.StandardException; 42 43 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 44 45 import org.apache.derby.iapi.sql.compile.CompilerContext; 46 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 47 import org.apache.derby.iapi.sql.compile.Optimizer; 48 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 49 import org.apache.derby.iapi.sql.compile.Optimizable; 50 import org.apache.derby.iapi.sql.compile.CostEstimate; 51 import org.apache.derby.iapi.sql.compile.AccessPath; 52 import org.apache.derby.iapi.sql.compile.JoinStrategy; 53 import org.apache.derby.iapi.sql.compile.RowOrdering; 54 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 55 56 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 57 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor; 58 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList; 59 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor; 60 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 61 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator; 62 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor; 63 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 64 import org.apache.derby.iapi.sql.dictionary.ViewDescriptor; 65 66 import org.apache.derby.iapi.sql.execute.ExecRow; 67 import org.apache.derby.iapi.sql.execute.ExecutionContext; 68 69 import org.apache.derby.iapi.sql.LanguageProperties; 70 71 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo; 72 import org.apache.derby.iapi.store.access.StoreCostController; 73 import org.apache.derby.iapi.store.access.ScanController; 74 import org.apache.derby.iapi.store.access.TransactionController; 75 76 import org.apache.derby.iapi.types.DataValueDescriptor; 77 78 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 79 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 80 81 import java.util.Enumeration ; 82 import java.util.Properties ; 83 import java.util.Vector ; 84 import java.util.HashSet ; 85 import java.util.Set ; 86 87 115 116 public class FromBaseTable extends FromTable 117 { 118 static final int UNSET = -1; 119 120 TableName tableName; 121 TableDescriptor tableDescriptor; 122 123 ConglomerateDescriptor baseConglomerateDescriptor; 124 ConglomerateDescriptor[] conglomDescs; 125 126 int updateOrDelete; 127 128 139 int bulkFetch = UNSET; 140 141 145 boolean bulkFetchTurnedOff; 146 147 private double singleScanRowCount; 148 149 private FormatableBitSet referencedCols; 150 private ResultColumnList templateColumns; 151 152 155 private String [] columnNames; 156 157 private boolean specialMaxScan; 160 161 private boolean distinctScan; 163 164 167 private boolean raDependentScan; 168 private String raParentResultSetId; 169 private long fkIndexConglomId; 170 private int[] fkColArray; 171 172 175 PredicateList baseTableRestrictionList; 176 PredicateList nonBaseTableRestrictionList; 177 PredicateList restrictionList; 178 PredicateList storeRestrictionList; 179 PredicateList nonStoreRestrictionList; 180 PredicateList requalificationRestrictionList; 181 182 public static final int UPDATE = 1; 183 public static final int DELETE = 2; 184 185 186 private boolean existsBaseTable; 187 private boolean isNotExists; private JBitSet dependencyMap; 189 190 private boolean getUpdateLocks; 191 192 213 public void init( 214 Object arg1, 215 Object arg2, 216 Object arg3, 217 Object arg4) 218 { 219 if (arg3 instanceof Integer ) 220 { 221 init(arg2, null); 222 this.tableName = (TableName) arg1; 223 this.updateOrDelete = ((Integer ) arg3).intValue(); 224 resultColumns = (ResultColumnList) arg4; 225 } 226 else 227 { 228 init(arg2, arg4); 229 this.tableName = (TableName) arg1; 230 resultColumns = (ResultColumnList) arg3; 231 } 232 233 setOrigTableName(this.tableName); 234 templateColumns = resultColumns; 235 } 236 237 240 public boolean LOJ_reorderable(int numTables) 241 throws StandardException 242 { 243 return false; 244 } 245 246 public JBitSet LOJgetReferencedTables(int numTables) 247 throws StandardException 248 { 249 JBitSet map = new JBitSet(numTables); 250 fillInReferencedTableMap(map); 251 return map; 252 } 253 254 257 258 263 public boolean nextAccessPath(Optimizer optimizer, 264 OptimizablePredicateList predList, 265 RowOrdering rowOrdering) 266 throws StandardException 267 { 268 String userSpecifiedIndexName = getUserSpecifiedIndexName(); 269 AccessPath ap = getCurrentAccessPath(); 270 ConglomerateDescriptor currentConglomerateDescriptor = 271 ap.getConglomerateDescriptor(); 272 273 optimizer.trace(Optimizer.CALLING_NEXT_ACCESS_PATH, 274 ((predList == null) ? 0 : predList.size()), 275 0, 0.0, getExposedName()); 276 277 281 rowOrdering.removeOptimizable(getTableNumber()); 282 283 286 if (userSpecifiedIndexName != null) 287 { 288 294 if (currentConglomerateDescriptor != null) 295 { 296 if ( ! super.nextAccessPath(optimizer, 297 predList, 298 rowOrdering) ) 299 { 300 currentConglomerateDescriptor = null; 301 } 302 } 303 else 304 { 305 optimizer.trace(Optimizer.LOOKING_FOR_SPECIFIED_INDEX, 306 tableNumber, 0, 0.0, userSpecifiedIndexName); 307 308 if (StringUtil.SQLToUpperCase(userSpecifiedIndexName).equals("NULL")) 309 { 310 311 currentConglomerateDescriptor = 312 tableDescriptor.getConglomerateDescriptor( 313 tableDescriptor.getHeapConglomerateId() 314 ); 315 } 316 else 317 { 318 319 getConglomDescs(); 320 321 for (int index = 0; index < conglomDescs.length; index++) 322 { 323 currentConglomerateDescriptor = conglomDescs[index]; 324 String conglomerateName = 325 currentConglomerateDescriptor.getConglomerateName(); 326 if (conglomerateName != null) 327 { 328 329 if (conglomerateName.equals(userSpecifiedIndexName)) 330 { 331 break; 332 } 333 } 334 } 335 336 337 if (SanityManager.DEBUG) 338 { 339 if (currentConglomerateDescriptor == null) 340 { 341 SanityManager.THROWASSERT( 342 "Expected to find match for forced index " + 343 userSpecifiedIndexName); 344 } 345 } 346 } 347 348 if ( ! super.nextAccessPath(optimizer, 349 predList, 350 rowOrdering)) 351 { 352 if (SanityManager.DEBUG) 353 { 354 SanityManager.THROWASSERT("No join strategy found"); 355 } 356 } 357 } 358 } 359 else 360 { 361 if (currentConglomerateDescriptor != null) 362 { 363 367 if ( ! super.nextAccessPath(optimizer, 368 predList, 369 rowOrdering)) 370 { 371 375 currentConglomerateDescriptor = getNextConglom(currentConglomerateDescriptor); 376 377 381 resetJoinStrategies(optimizer); 382 383 if ( ! super.nextAccessPath(optimizer, 384 predList, 385 rowOrdering)) 386 { 387 if (SanityManager.DEBUG) 388 { 389 SanityManager.THROWASSERT("No join strategy found"); 390 } 391 } 392 } 393 } 394 else 395 { 396 397 currentConglomerateDescriptor = getFirstConglom(); 398 399 if ( ! super.nextAccessPath(optimizer, 400 predList, 401 rowOrdering)) 402 { 403 if (SanityManager.DEBUG) 404 { 405 SanityManager.THROWASSERT("No join strategy found"); 406 } 407 } 408 } 409 } 410 411 if (currentConglomerateDescriptor == null) 412 { 413 optimizer.trace(Optimizer.NO_MORE_CONGLOMERATES, tableNumber, 0, 0.0, null); 414 } 415 else 416 { 417 currentConglomerateDescriptor.setColumnNames(columnNames); 418 optimizer.trace(Optimizer.CONSIDERING_CONGLOMERATE, tableNumber, 0, 0.0, 419 currentConglomerateDescriptor); 420 } 421 422 425 if (currentConglomerateDescriptor != null) 426 { 427 if ( ! currentConglomerateDescriptor.isIndex()) 428 { 429 435 if (! isOneRowResultSet(predList)) 436 { 437 optimizer.trace(Optimizer.ADDING_UNORDERED_OPTIMIZABLE, 438 ((predList == null) ? 0 : predList.size()), 439 0, 0.0, null); 440 441 rowOrdering.addUnorderedOptimizable(this); 442 } 443 else 444 { 445 optimizer.trace(Optimizer.SCANNING_HEAP_FULL_MATCH_ON_UNIQUE_KEY, 446 0, 0, 0.0, null); 447 } 448 } 449 else 450 { 451 IndexRowGenerator irg = 452 currentConglomerateDescriptor.getIndexDescriptor(); 453 454 int[] baseColumnPositions = irg.baseColumnPositions(); 455 boolean[] isAscending = irg.isAscending(); 456 457 for (int i = 0; i < baseColumnPositions.length; i++) 458 { 459 472 if ( ! rowOrdering.orderedOnColumn(isAscending[i] ? 473 RowOrdering.ASCENDING : 474 RowOrdering.DESCENDING, 475 getTableNumber(), 476 baseColumnPositions[i])) 477 { 478 rowOrdering.nextOrderPosition(isAscending[i] ? 479 RowOrdering.ASCENDING : 480 RowOrdering.DESCENDING); 481 482 rowOrdering.addOrderedColumn(isAscending[i] ? 483 RowOrdering.ASCENDING : 484 RowOrdering.DESCENDING, 485 getTableNumber(), 486 baseColumnPositions[i]); 487 } 488 } 489 } 490 } 491 492 ap.setConglomerateDescriptor(currentConglomerateDescriptor); 493 494 return currentConglomerateDescriptor != null; 495 } 496 497 498 protected boolean canBeOrdered() 499 { 500 return true; 501 } 502 503 508 public CostEstimate optimizeIt( 509 Optimizer optimizer, 510 OptimizablePredicateList predList, 511 CostEstimate outerCost, 512 RowOrdering rowOrdering) 513 throws StandardException 514 { 515 optimizer.costOptimizable( 516 this, 517 tableDescriptor, 518 getCurrentAccessPath().getConglomerateDescriptor(), 519 predList, 520 outerCost); 521 522 return getCurrentAccessPath().getCostEstimate(); 526 } 527 528 529 public TableDescriptor getTableDescriptor() 530 { 531 return tableDescriptor; 532 } 533 534 535 539 public boolean isMaterializable() 540 throws StandardException 541 { 542 543 return true; 544 } 545 546 547 552 553 public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate) 554 throws StandardException 555 { 556 if (SanityManager.DEBUG) 557 { 558 SanityManager.ASSERT(optimizablePredicate instanceof Predicate, 559 "optimizablePredicate expected to be instanceof Predicate"); 560 } 561 562 563 restrictionList.addPredicate((Predicate) optimizablePredicate); 564 565 return true; 566 } 567 568 573 public void pullOptPredicates( 574 OptimizablePredicateList optimizablePredicates) 575 throws StandardException 576 { 577 for (int i = restrictionList.size() - 1; i >= 0; i--) { 578 optimizablePredicates.addOptPredicate( 579 restrictionList.getOptPredicate(i)); 580 restrictionList.removeOptPredicate(i); 581 } 582 } 583 584 588 public boolean isCoveringIndex(ConglomerateDescriptor cd) throws StandardException 589 { 590 boolean coveringIndex = true; 591 IndexRowGenerator irg; 592 int[] baseCols; 593 int colPos; 594 595 596 if ( ! cd.isIndex()) 597 return false; 598 599 irg = cd.getIndexDescriptor(); 600 baseCols = irg.baseColumnPositions(); 601 602 603 int rclSize = resultColumns.size(); 604 for (int index = 0; index < rclSize; index++) 605 { 606 ResultColumn rc = (ResultColumn) resultColumns.elementAt(index); 607 608 609 if (! rc.isReferenced()) 610 { 611 continue; 612 } 613 614 618 if (rc.getExpression() instanceof ConstantNode) 619 { 620 continue; 621 } 622 623 coveringIndex = false; 624 625 colPos = rc.getColumnPosition(); 626 627 628 for (int i = 0; i < baseCols.length; i++) 629 { 630 if (colPos == baseCols[i]) 631 { 632 coveringIndex = true; 633 break; 634 } 635 } 636 637 638 if (! coveringIndex) 639 { 640 break; 641 } 642 } 643 return coveringIndex; 644 } 645 646 649 public void verifyProperties(DataDictionary dDictionary) 650 throws StandardException 651 { 652 if (tableProperties == null) 653 { 654 return; 655 } 656 666 boolean indexSpecified = false; 667 boolean constraintSpecified = false; 668 ConstraintDescriptor consDesc = null; 669 Enumeration e = tableProperties.keys(); 670 671 StringUtil.SQLEqualsIgnoreCase(tableDescriptor.getSchemaName(), 672 "SYS"); 673 while (e.hasMoreElements()) 674 { 675 String key = (String ) e.nextElement(); 676 String value = (String ) tableProperties.get(key); 677 678 if (key.equals("index")) 679 { 680 if (constraintSpecified) 682 { 683 throw StandardException.newException(SQLState.LANG_BOTH_FORCE_INDEX_AND_CONSTRAINT_SPECIFIED, 684 getBaseTableName()); 685 } 686 indexSpecified = true; 687 688 689 if (! StringUtil.SQLToUpperCase(value).equals("NULL")) 690 { 691 ConglomerateDescriptor cd = null; 692 ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors(); 693 694 for (int index = 0; index < cds.length; index++) 695 { 696 cd = cds[index]; 697 String conglomerateName = cd.getConglomerateName(); 698 if (conglomerateName != null) 699 { 700 if (conglomerateName.equals(value)) 701 { 702 break; 703 } 704 } 705 cd = null; 707 } 708 709 if (cd == null) 711 { 712 throw StandardException.newException(SQLState.LANG_INVALID_FORCED_INDEX1, 713 value, getBaseTableName()); 714 } 715 716 getCompilerContext().createDependency(cd); 717 } 718 } 719 else if (key.equals("constraint")) 720 { 721 if (indexSpecified) 723 { 724 throw StandardException.newException(SQLState.LANG_BOTH_FORCE_INDEX_AND_CONSTRAINT_SPECIFIED, 725 getBaseTableName()); 726 } 727 constraintSpecified = true; 728 729 if (! StringUtil.SQLToUpperCase(value).equals("NULL")) 730 { 731 consDesc = 732 dDictionary.getConstraintDescriptorByName( 733 tableDescriptor, (SchemaDescriptor)null, value, 734 false); 735 736 739 if ((consDesc == null) || ! consDesc.hasBackingIndex()) 740 { 741 throw StandardException.newException(SQLState.LANG_INVALID_FORCED_INDEX2, 742 value, getBaseTableName()); 743 } 744 745 746 getCompilerContext().createDependency(consDesc); 747 } 748 } 749 else if (key.equals("joinStrategy")) 750 { 751 userSpecifiedJoinStrategy = StringUtil.SQLToUpperCase(value); 752 } 753 else if (key.equals("hashInitialCapacity")) 754 { 755 initialCapacity = getIntProperty(value, key); 756 757 if (initialCapacity <= 0) 759 { 760 throw StandardException.newException(SQLState.LANG_INVALID_HASH_INITIAL_CAPACITY, 761 String.valueOf(initialCapacity)); 762 } 763 } 764 else if (key.equals("hashLoadFactor")) 765 { 766 try 767 { 768 loadFactor = Float.valueOf(value).floatValue(); 769 } 770 catch (NumberFormatException nfe) 771 { 772 throw StandardException.newException(SQLState.LANG_INVALID_NUMBER_FORMAT_FOR_OVERRIDE, 773 value, key); 774 } 775 776 if (loadFactor <= 0.0 || loadFactor > 1.0) 778 { 779 throw StandardException.newException(SQLState.LANG_INVALID_HASH_LOAD_FACTOR, 780 value); 781 } 782 } 783 else if (key.equals("hashMaxCapacity")) 784 { 785 maxCapacity = getIntProperty(value, key); 786 787 if (maxCapacity <= 0) 789 { 790 throw StandardException.newException(SQLState.LANG_INVALID_HASH_MAX_CAPACITY, 791 String.valueOf(maxCapacity)); 792 } 793 } 794 else if (key.equals("bulkFetch")) 795 { 796 bulkFetch = getIntProperty(value, key); 797 798 if (bulkFetch <= 0) 800 { 801 throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_VALUE, 802 String.valueOf(bulkFetch)); 803 } 804 805 if (forUpdate()) 807 { 808 throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_UPDATEABLE); 809 } 810 } 811 else 812 { 813 throw StandardException.newException(SQLState.LANG_INVALID_FROM_TABLE_PROPERTY, key, 815 "index, constraint, joinStrategy"); 816 } 817 } 818 819 829 if (constraintSpecified && consDesc != null) 830 { 831 ConglomerateDescriptor cd = 832 dDictionary.getConglomerateDescriptor( 833 consDesc.getConglomerateId()); 834 String indexName = cd.getConglomerateName(); 835 836 tableProperties.remove("constraint"); 837 tableProperties.put("index", indexName); 838 } 839 } 840 841 842 public String getBaseTableName() 843 { 844 return tableName.getTableName(); 845 } 846 847 848 public void startOptimizing(Optimizer optimizer, RowOrdering rowOrdering) 849 { 850 AccessPath ap = getCurrentAccessPath(); 851 AccessPath bestAp = getBestAccessPath(); 852 AccessPath bestSortAp = getBestSortAvoidancePath(); 853 854 ap.setConglomerateDescriptor((ConglomerateDescriptor) null); 855 bestAp.setConglomerateDescriptor((ConglomerateDescriptor) null); 856 bestSortAp.setConglomerateDescriptor((ConglomerateDescriptor) null); 857 ap.setCoveringIndexScan(false); 858 bestAp.setCoveringIndexScan(false); 859 bestSortAp.setCoveringIndexScan(false); 860 ap.setLockMode(0); 861 bestAp.setLockMode(0); 862 bestSortAp.setLockMode(0); 863 864 869 CostEstimate costEstimate = getCostEstimate(optimizer); 870 ap.setCostEstimate(costEstimate); 871 872 877 costEstimate.setCost(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 878 879 super.startOptimizing(optimizer, rowOrdering); 880 } 881 882 883 public int convertAbsoluteToRelativeColumnPosition(int absolutePosition) 884 { 885 return mapAbsoluteToRelativeColumnPosition(absolutePosition); 886 } 887 888 893 public CostEstimate estimateCost(OptimizablePredicateList predList, 894 ConglomerateDescriptor cd, 895 CostEstimate outerCost, 896 Optimizer optimizer, 897 RowOrdering rowOrdering) 898 throws StandardException 899 { 900 double cost; 901 boolean statisticsForTable = false; 902 boolean statisticsForConglomerate = false; 903 906 PredicateList unknownPredicateList = null; 907 908 if (optimizer.useStatistics() && predList != null) 909 { 910 913 statisticsForConglomerate = tableDescriptor.statisticsExist(cd); 914 statisticsForTable = tableDescriptor.statisticsExist(null); 915 unknownPredicateList = new PredicateList(); 916 predList.copyPredicatesToOtherList(unknownPredicateList); 917 918 } 919 920 AccessPath currentAccessPath = getCurrentAccessPath(); 921 JoinStrategy currentJoinStrategy = 922 currentAccessPath.getJoinStrategy(); 923 924 optimizer.trace(Optimizer.ESTIMATING_COST_OF_CONGLOMERATE, 925 tableNumber, 0, 0.0, cd); 926 927 928 double tableUniquenessFactor = 929 optimizer.uniqueJoinWithOuterTable(predList); 930 931 boolean oneRowResultSetForSomeConglom = isOneRowResultSet(predList); 932 933 934 baseTableRestrictionList.removeAllElements(); 935 936 currentJoinStrategy.getBasePredicates(predList, 937 baseTableRestrictionList, 938 this); 939 940 941 StoreCostController scc = getStoreCostController(cd); 942 943 CostEstimate costEstimate = getScratchCostEstimate(optimizer); 944 945 946 947 948 if (isOneRowResultSet(cd, baseTableRestrictionList)) 949 { 950 955 rowOrdering.optimizableAlwaysOrdered(this); 956 957 singleScanRowCount = 1.0; 958 959 960 cost = scc.getFetchFromFullKeyCost( 963 (FormatableBitSet) null, 964 0); 965 966 optimizer.trace(Optimizer.MATCH_SINGLE_ROW_COST, 967 tableNumber, 0, cost, null); 968 969 costEstimate.setCost(cost, 1.0d, 1.0d); 970 971 977 double newCost = costEstimate.getEstimatedCost(); 978 979 if (currentJoinStrategy.multiplyBaseCostByOuterRows()) 980 { 981 newCost *= outerCost.rowCount(); 982 } 983 984 costEstimate.setCost( 985 newCost, 986 costEstimate.rowCount() * outerCost.rowCount(), 987 costEstimate.singleScanRowCount()); 988 989 996 boolean constantStartStop = true; 997 for (int i = 0; i < predList.size(); i++) 998 { 999 OptimizablePredicate pred = predList.getOptPredicate(i); 1000 1001 1005 if ( ! (pred.isStartKey() || pred.isStopKey())) 1006 { 1007 break; 1008 } 1009 1010 1011 if ( ! pred.getReferencedMap().hasSingleBitSet()) 1012 { 1013 constantStartStop = false; 1014 break; 1015 } 1016 } 1017 1018 if (constantStartStop) 1019 { 1020 currentAccessPath.setLockMode( 1021 TransactionController.MODE_RECORD); 1022 1023 optimizer.trace(Optimizer.ROW_LOCK_ALL_CONSTANT_START_STOP, 1024 0, 0, 0.0, null); 1025 } 1026 else 1027 { 1028 setLockingBasedOnThreshold(optimizer, costEstimate.rowCount()); 1029 } 1030 1031 optimizer.trace(Optimizer.COST_OF_N_SCANS, 1032 tableNumber, 0, outerCost.rowCount(), costEstimate); 1033 1034 1035 if (cd.isIndex() && ( ! isCoveringIndex(cd) ) ) 1036 { 1037 double singleFetchCost = 1038 getBaseCostController().getFetchFromRowLocationCost( 1039 (FormatableBitSet) null, 1040 0); 1041 cost = singleFetchCost * costEstimate.rowCount(); 1042 1043 costEstimate.setEstimatedCost( 1044 costEstimate.getEstimatedCost() + cost); 1045 1046 optimizer.trace(Optimizer.NON_COVERING_INDEX_COST, 1047 tableNumber, 0, cost, null); 1048 } 1049 } 1050 else 1051 { 1052 1053 1054 1091 double extraFirstColumnSelectivity = 1.0d; 1092 double extraStartStopSelectivity = 1.0d; 1093 double extraQualifierSelectivity = 1.0d; 1094 double extraNonQualifierSelectivity = 1.0d; 1095 double statStartStopSelectivity = 1.0d; 1096 double statCompositeSelectivity = 1.0d; 1097 1098 int numExtraFirstColumnPreds = 0; 1099 int numExtraStartStopPreds = 0; 1100 int numExtraQualifiers = 0; 1101 int numExtraNonQualifiers = 0; 1102 1103 1114 boolean startGap = false; 1115 boolean stopGap = false; 1116 boolean seenFirstColumn = false; 1117 1118 1126 boolean constantStartStop = true; 1127 boolean startStopFound = false; 1128 1129 1130 int startKeyNum = 0; 1131 int stopKeyNum = 0; 1132 OptimizablePredicate pred; 1133 int predListSize; 1134 1135 if (predList != null) 1136 predListSize = baseTableRestrictionList.size(); 1137 else 1138 predListSize = 0; 1139 1140 int startStopPredCount = 0; 1141 ColumnReference firstColumn = null; 1142 for (int i = 0; i < predListSize; i++) 1143 { 1144 pred = baseTableRestrictionList.getOptPredicate(i); 1145 boolean startKey = pred.isStartKey(); 1146 boolean stopKey = pred.isStopKey(); 1147 if (startKey || stopKey) 1148 { 1149 startStopFound = true; 1150 1151 if ( ! pred.getReferencedMap().hasSingleBitSet()) 1152 { 1153 constantStartStop = false; 1154 } 1155 1156 boolean knownConstant = 1157 pred.compareWithKnownConstant(this, true); 1158 if (startKey) 1159 { 1160 if (knownConstant && ( ! startGap ) ) 1161 { 1162 startKeyNum++; 1163 if (unknownPredicateList != null) 1164 unknownPredicateList.removeOptPredicate(pred); 1165 } 1166 else 1167 { 1168 startGap = true; 1169 } 1170 } 1171 1172 if (stopKey) 1173 { 1174 if (knownConstant && ( ! stopGap ) ) 1175 { 1176 stopKeyNum++; 1177 if (unknownPredicateList != null) 1178 unknownPredicateList.removeOptPredicate(pred); 1179 } 1180 else 1181 { 1182 stopGap = true; 1183 } 1184 } 1185 1186 1190 if (startGap || stopGap) 1191 { 1192 if (baseTableRestrictionList.isRedundantPredicate(i)) 1194 continue; 1195 1196 if (startKey && stopKey) 1197 startStopPredCount++; 1198 1199 if (pred.getIndexPosition() == 0) 1200 { 1201 extraFirstColumnSelectivity *= 1202 pred.selectivity(this); 1203 if (! seenFirstColumn) 1204 { 1205 ValueNode relNode = ((Predicate) pred).getAndNode().getLeftOperand(); 1206 if (relNode instanceof BinaryRelationalOperatorNode) 1207 firstColumn = ((BinaryRelationalOperatorNode) relNode).getColumnOperand(this); 1208 seenFirstColumn = true; 1209 } 1210 } 1211 else 1212 { 1213 extraStartStopSelectivity *= pred.selectivity(this); 1214 numExtraStartStopPreds++; 1215 } 1216 } 1217 } 1218 else 1219 { 1220 if (baseTableRestrictionList.isRedundantPredicate(i)) 1222 { 1223 continue; 1224 } 1225 1226 1230 if (pred instanceof Predicate) 1231 { 1232 ValueNode leftOpnd = ((Predicate) pred).getAndNode().getLeftOperand(); 1233 if (firstColumn != null && leftOpnd instanceof LikeEscapeOperatorNode) 1234 { 1235 LikeEscapeOperatorNode likeNode = (LikeEscapeOperatorNode) leftOpnd; 1236 if (likeNode.getLeftOperand().requiresTypeFromContext()) 1237 { 1238 ValueNode receiver = ((TernaryOperatorNode) likeNode).getReceiver(); 1239 if (receiver instanceof ColumnReference) 1240 { 1241 ColumnReference cr = (ColumnReference) receiver; 1242 if (cr.getTableNumber() == firstColumn.getTableNumber() && 1243 cr.getColumnNumber() == firstColumn.getColumnNumber()) 1244 extraFirstColumnSelectivity *= 0.2; 1245 } 1246 } 1247 } 1248 } 1249 1250 if (pred.isQualifier()) 1251 { 1252 extraQualifierSelectivity *= pred.selectivity(this); 1253 numExtraQualifiers++; 1254 } 1255 else 1256 { 1257 extraNonQualifierSelectivity *= pred.selectivity(this); 1258 numExtraNonQualifiers++; 1259 } 1260 1261 1266 startGap = true; 1267 stopGap = true; 1268 } 1269 } 1270 1271 if (unknownPredicateList != null) 1272 { 1273 statCompositeSelectivity = unknownPredicateList.selectivity(this); 1274 if (statCompositeSelectivity == -1.0d) 1275 statCompositeSelectivity = 1.0d; 1276 } 1277 1278 if (seenFirstColumn && statisticsForConglomerate && 1279 (startStopPredCount > 0)) 1280 { 1281 statStartStopSelectivity = 1282 tableDescriptor.selectivityForConglomerate(cd, startStopPredCount); 1283 } 1284 1285 1290 extraNonQualifierSelectivity *= 1291 currentJoinStrategy.nonBasePredicateSelectivity(this, predList); 1292 1293 1294 DataValueDescriptor[] startKeys; 1295 DataValueDescriptor[] stopKeys; 1296 1297 if (startKeyNum > 0) 1298 startKeys = new DataValueDescriptor[startKeyNum]; 1299 else 1300 startKeys = null; 1301 1302 if (stopKeyNum > 0) 1303 stopKeys = new DataValueDescriptor[stopKeyNum]; 1304 else 1305 stopKeys = null; 1306 1307 startKeyNum = 0; 1308 stopKeyNum = 0; 1309 startGap = false; 1310 stopGap = false; 1311 1312 for (int i = 0; i < predListSize; i++) 1313 { 1314 pred = baseTableRestrictionList.getOptPredicate(i); 1315 boolean startKey = pred.isStartKey(); 1316 boolean stopKey = pred.isStopKey(); 1317 1318 if (startKey || stopKey) 1319 { 1320 boolean knownConstant = pred.compareWithKnownConstant(this, true); 1321 1322 if (startKey) 1323 { 1324 if (knownConstant && ( ! startGap ) ) 1325 { 1326 startKeys[startKeyNum] = pred.getCompareValue(this); 1327 startKeyNum++; 1328 } 1329 else 1330 { 1331 startGap = true; 1332 } 1333 } 1334 1335 if (stopKey) 1336 { 1337 if (knownConstant && ( ! stopGap ) ) 1338 { 1339 stopKeys[stopKeyNum] = pred.getCompareValue(this); 1340 stopKeyNum++; 1341 } 1342 else 1343 { 1344 stopGap = true; 1345 } 1346 } 1347 } 1348 else 1349 { 1350 startGap = true; 1351 stopGap = true; 1352 } 1353 } 1354 1355 int startOperator; 1356 int stopOperator; 1357 1358 if (baseTableRestrictionList != null) 1359 { 1360 startOperator = baseTableRestrictionList.startOperator(this); 1361 stopOperator = baseTableRestrictionList.stopOperator(this); 1362 } 1363 else 1364 { 1365 1369 startOperator = ScanController.NA; 1370 stopOperator = ScanController.NA; 1371 } 1372 1373 1377 DataValueDescriptor[] rowTemplate = 1378 getRowTemplate(cd, getBaseCostController()); 1379 1380 1388 long baseRC = (startKeys != null || stopKeys != null) ? baseRowCount() : baseRowCount() + 5; 1389 1390 scc.getScanCost( 1391 currentJoinStrategy.scanCostType(), 1392 baseRC, 1393 1, 1394 forUpdate(), 1395 (FormatableBitSet) null, 1396 rowTemplate, 1397 startKeys, 1398 startOperator, 1399 stopKeys, 1400 stopOperator, 1401 false, 1402 0, 1403 costEstimate); 1404 1405 1412 double initialPositionCost = 0.0; 1413 if (cd.isIndex()) 1414 { 1415 initialPositionCost = scc.getFetchFromFullKeyCost((FormatableBitSet) null, 0); 1416 1423 if (oneRowResultSetForSomeConglom && costEstimate.rowCount() <= 1) 1424 { 1425 costEstimate.setCost(costEstimate.getEstimatedCost() * 2, 1426 costEstimate.rowCount() + 2, 1427 costEstimate.singleScanRowCount() + 2); 1428 } 1429 } 1430 1431 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN1, 1432 tableNumber, 0, 0.0, cd); 1433 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN2, 1434 tableNumber, 0, 0.0, costEstimate); 1435 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN3, 1436 numExtraFirstColumnPreds, 0, 1437 extraFirstColumnSelectivity, null); 1438 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN4, 1439 numExtraStartStopPreds, 0, 1440 extraStartStopSelectivity, null); 1441 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN7, 1442 startStopPredCount, 0, 1443 statStartStopSelectivity, null); 1444 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN5, 1445 numExtraQualifiers, 0, 1446 extraQualifierSelectivity, null); 1447 optimizer.trace(Optimizer.COST_OF_CONGLOMERATE_SCAN6, 1448 numExtraNonQualifiers, 0, 1449 extraNonQualifierSelectivity, null); 1450 1451 1455 double initialRowCount = costEstimate.rowCount(); 1456 1457 if (statStartStopSelectivity != 1.0d) 1458 { 1459 1467 costEstimate.setCost( 1468 scanCostAfterSelectivity(costEstimate.getEstimatedCost(), 1469 initialPositionCost, 1470 statStartStopSelectivity, 1471 oneRowResultSetForSomeConglom), 1472 costEstimate.rowCount() * statStartStopSelectivity, 1473 costEstimate.singleScanRowCount() * 1474 statStartStopSelectivity); 1475 optimizer.trace(Optimizer.COST_INCLUDING_STATS_FOR_INDEX, 1476 tableNumber, 0, 0.0, costEstimate); 1477 1478 } 1479 else 1480 { 1481 1487 if (extraFirstColumnSelectivity != 1.0d) 1488 { 1489 costEstimate.setCost( 1490 scanCostAfterSelectivity(costEstimate.getEstimatedCost(), 1491 initialPositionCost, 1492 extraFirstColumnSelectivity, 1493 oneRowResultSetForSomeConglom), 1494 costEstimate.rowCount() * extraFirstColumnSelectivity, 1495 costEstimate.singleScanRowCount() * extraFirstColumnSelectivity); 1496 1497 optimizer.trace(Optimizer.COST_INCLUDING_EXTRA_1ST_COL_SELECTIVITY, 1498 tableNumber, 0, 0.0, costEstimate); 1499 } 1500 1501 1505 if (extraStartStopSelectivity != 1.0d) 1506 { 1507 costEstimate.setCost( 1508 costEstimate.getEstimatedCost(), 1509 costEstimate.rowCount() * extraStartStopSelectivity, 1510 costEstimate.singleScanRowCount() * extraStartStopSelectivity); 1511 1512 optimizer.trace(Optimizer.COST_INCLUDING_EXTRA_START_STOP, 1513 tableNumber, 0, 0.0, costEstimate); 1514 } 1515 } 1516 1517 1523 if (! startStopFound) 1524 { 1525 currentAccessPath.setLockMode( 1526 TransactionController.MODE_TABLE); 1527 1528 optimizer.trace(Optimizer.TABLE_LOCK_NO_START_STOP, 1529 0, 0, 0.0, null); 1530 } 1531 else 1532 { 1533 1542 double rowsTouched = costEstimate.rowCount(); 1543 1544 if ( (! constantStartStop) && 1545 currentJoinStrategy.multiplyBaseCostByOuterRows()) 1546 { 1547 1571 double r = baseRowCount(); 1572 if (r > 0.0) 1573 { 1574 double s = costEstimate.rowCount(); 1575 double o = outerCost.rowCount(); 1576 double pRowsNotTouchedPerScan = 1.0 - (s / r); 1577 double pRowsNotTouchedAllScans = 1578 Math.pow(pRowsNotTouchedPerScan, o); 1579 double pRowsTouchedAllScans = 1580 1.0 - pRowsNotTouchedAllScans; 1581 double rowsTouchedAllScans = 1582 r * pRowsTouchedAllScans; 1583 1584 rowsTouched = rowsTouchedAllScans; 1585 } 1586 else 1587 { 1588 1589 rowsTouched = optimizer.tableLockThreshold() + 1; 1590 } 1591 } 1592 1593 setLockingBasedOnThreshold(optimizer, rowsTouched); 1594 } 1595 1596 1605 if (cd.isIndex() && ( ! isCoveringIndex(cd) ) ) 1606 { 1607 double singleFetchCost = 1608 getBaseCostController().getFetchFromRowLocationCost( 1609 (FormatableBitSet) null, 1610 0); 1611 1612 cost = singleFetchCost * costEstimate.rowCount(); 1613 1614 costEstimate.setEstimatedCost( 1615 costEstimate.getEstimatedCost() + cost); 1616 1617 optimizer.trace(Optimizer.COST_OF_NONCOVERING_INDEX, 1618 tableNumber, 0, 0.0, costEstimate); 1619 } 1620 1621 1625 if (extraQualifierSelectivity != 1.0d) 1626 { 1627 costEstimate.setCost( 1628 costEstimate.getEstimatedCost(), 1629 costEstimate.rowCount() * extraQualifierSelectivity, 1630 costEstimate.singleScanRowCount() * extraQualifierSelectivity); 1631 1632 optimizer.trace(Optimizer.COST_INCLUDING_EXTRA_QUALIFIER_SELECTIVITY, 1633 tableNumber, 0, 0.0, costEstimate); 1634 } 1635 1636 singleScanRowCount = costEstimate.singleScanRowCount(); 1637 1638 1648 double newCost = costEstimate.getEstimatedCost(); 1649 double rowCount = costEstimate.rowCount(); 1650 1651 1666 if (currentJoinStrategy.multiplyBaseCostByOuterRows()) 1667 { 1668 newCost *= outerCost.rowCount(); 1669 } 1670 1671 rowCount *= outerCost.rowCount(); 1672 initialRowCount *= outerCost.rowCount(); 1673 1674 1675 1682 if (oneRowResultSetForSomeConglom) 1683 { 1684 if (outerCost.rowCount() < rowCount) 1685 { 1686 rowCount = outerCost.rowCount(); 1687 } 1688 } 1689 1690 1698 if (cd.isIndex() && startStopFound && ( ! constantStartStop ) ) 1699 { 1700 1707 double scanUniquenessFactor = 1708 optimizer.uniqueJoinWithOuterTable(baseTableRestrictionList); 1709 if (scanUniquenessFactor > 0.0) 1710 { 1711 1717 double maxRows = 1718 ((double) baseRowCount()) / scanUniquenessFactor; 1719 if (rowCount > maxRows) 1720 { 1721 1726 newCost *= (maxRows / rowCount); 1727 } 1728 } 1729 } 1730 1731 1732 if (tableUniquenessFactor > 0.0) 1733 { 1734 1740 double maxRows = 1741 ((double) baseRowCount()) / tableUniquenessFactor; 1742 if (rowCount > maxRows) 1743 { 1744 1748 rowCount = maxRows; 1749 } 1750 } 1751 1752 costEstimate.setCost( 1753 newCost, 1754 rowCount, 1755 costEstimate.singleScanRowCount()); 1756 1757 1758 optimizer.trace(Optimizer.COST_OF_N_SCANS, 1759 tableNumber, 0, outerCost.rowCount(), costEstimate); 1760 1761 1765 double rc = -1, src = -1; 1766 if (existsBaseTable) 1767 rc = src = 1; 1768 else if (extraNonQualifierSelectivity != 1.0d) 1772 { 1773 rc = oneRowResultSetForSomeConglom ? costEstimate.rowCount() : 1774 costEstimate.rowCount() * extraNonQualifierSelectivity; 1775 src = costEstimate.singleScanRowCount() * extraNonQualifierSelectivity; 1776 } 1777 if (rc != -1) { 1779 costEstimate.setCost(costEstimate.getEstimatedCost(), rc, src); 1780 optimizer.trace(Optimizer.COST_INCLUDING_EXTRA_NONQUALIFIER_SELECTIVITY, 1781 tableNumber, 0, 0.0, costEstimate); 1782 } 1783 1784 recomputeRowCount: 1785 if (statisticsForTable && !oneRowResultSetForSomeConglom && 1786 (statCompositeSelectivity != 1.0d)) 1787 { 1788 1793 1794 double compositeStatRC = initialRowCount * statCompositeSelectivity; 1795 optimizer.trace(Optimizer.COMPOSITE_SEL_FROM_STATS, 1796 0, 0, statCompositeSelectivity, null); 1797 1798 1799 if (tableUniquenessFactor > 0.0) 1800 { 1801 1806 if (compositeStatRC > (baseRowCount() * 1807 tableUniquenessFactor)) 1808 1809 { 1810 1811 break recomputeRowCount; 1812 } 1813 } 1814 1815 1821 costEstimate.setCost(costEstimate.getEstimatedCost(), 1822 compositeStatRC, 1823 (existsBaseTable) ? 1824 1 : 1825 compositeStatRC / outerCost.rowCount()); 1826 1827 optimizer.trace(Optimizer.COST_INCLUDING_COMPOSITE_SEL_FROM_STATS, 1828 tableNumber, 0, 0.0, costEstimate); 1829 } 1830 } 1831 1832 1833 currentJoinStrategy.putBasePredicates(predList, 1834 baseTableRestrictionList); 1835 return costEstimate; 1836 } 1837 1838 private double scanCostAfterSelectivity(double originalScanCost, 1839 double initialPositionCost, 1840 double selectivity, 1841 boolean anotherIndexUnique) 1842 throws StandardException 1843 { 1844 1850 if (anotherIndexUnique) 1851 { 1852 double r = baseRowCount(); 1853 if (r > 0.0) 1854 { 1855 double minSelectivity = 2.0 / r; 1856 if (minSelectivity > selectivity) 1857 selectivity = minSelectivity; 1858 } 1859 } 1860 1861 1868 double afterInitialCost = (originalScanCost - initialPositionCost) * 1869 selectivity; 1870 if (afterInitialCost < 0) 1871 afterInitialCost = 0; 1872 return initialPositionCost + afterInitialCost; 1873 } 1874 1875 private void setLockingBasedOnThreshold( 1876 Optimizer optimizer, double rowsTouched) 1877 { 1878 1884 getCurrentAccessPath().setLockMode( 1885 TransactionController.MODE_RECORD); 1886 } 1887 1888 1889 public boolean isBaseTable() 1890 { 1891 return true; 1892 } 1893 1894 1895 public boolean forUpdate() 1896 { 1897 1902 return (updateOrDelete != 0) || cursorTargetTable || getUpdateLocks; 1903 } 1904 1905 1906 public int initialCapacity() 1907 { 1908 return initialCapacity; 1909 } 1910 1911 1912 public float loadFactor() 1913 { 1914 return loadFactor; 1915 } 1916 1917 1920 public boolean memoryUsageOK(double rowCount, int maxMemoryPerTable) 1921 throws StandardException 1922 { 1923 return super.memoryUsageOK(singleScanRowCount, maxMemoryPerTable); 1924 } 1925 1926 1929 public boolean isTargetTable() 1930 { 1931 return (updateOrDelete != 0); 1932 } 1933 1934 1937 public double uniqueJoin(OptimizablePredicateList predList) 1938 throws StandardException 1939 { 1940 double retval = -1.0; 1941 PredicateList pl = (PredicateList) predList; 1942 int numColumns = getTableDescriptor().getNumberOfColumns(); 1943 int tableNumber = getTableNumber(); 1944 1945 int[] tableNumbers = new int[0]; 1951 JBitSet[] tableColMap = new JBitSet[1]; 1952 tableColMap[0] = new JBitSet(numColumns + 1); 1953 1954 pl.checkTopPredicatesForEqualsConditions(tableNumber, 1955 null, 1956 tableNumbers, 1957 tableColMap, 1958 false); 1959 1960 if (supersetOfUniqueIndex(tableColMap)) 1961 { 1962 retval = 1963 getBestAccessPath().getCostEstimate().singleScanRowCount(); 1964 } 1965 1966 return retval; 1967 } 1968 1969 1974 public boolean isOneRowScan() 1975 throws StandardException 1976 { 1977 1980 if (existsBaseTable) 1981 { 1982 return false; 1983 } 1984 1985 1986 return super.isOneRowScan(); 1987 } 1988 1989 1992 public boolean legalJoinOrder(JBitSet assignedTableMap) 1993 { 1994 if (existsBaseTable) 1996 { 1997 1998 return assignedTableMap.contains(dependencyMap); 1999 } 2000 return true; 2001 } 2002 2003 2009 2010 public String toString() 2011 { 2012 if (SanityManager.DEBUG) 2013 { 2014 return "tableName: " + 2015 (tableName != null ? tableName.toString() : "null") + "\n" + 2016 "tableDescriptor: " + tableDescriptor + "\n" + 2017 "updateOrDelete: " + updateOrDelete + "\n" + 2018 (tableProperties != null ? 2019 tableProperties.toString() : "null") + "\n" + 2020 "existsBaseTable: " + existsBaseTable + "\n" + 2021 "dependencyMap: " + 2022 (dependencyMap != null 2023 ? dependencyMap.toString() 2024 : "null") + "\n" + 2025 super.toString(); 2026 } 2027 else 2028 { 2029 return ""; 2030 } 2031 } 2032 2033 2039 boolean getExistsBaseTable() 2040 { 2041 return existsBaseTable; 2042 } 2043 2044 2052 void setExistsBaseTable(boolean existsBaseTable, JBitSet dependencyMap, boolean isNotExists) 2053 { 2054 this.existsBaseTable = existsBaseTable; 2055 this.isNotExists = isNotExists; 2056 2057 2058 if (existsBaseTable) 2059 { 2060 this.dependencyMap = dependencyMap; 2061 } 2062 else 2063 { 2064 this.dependencyMap = null; 2065 } 2066 } 2067 2068 2073 void clearDependency(Vector locations) 2074 { 2075 if (this.dependencyMap != null) 2076 { 2077 for (int i = 0; i < locations.size() ; i++) 2078 this.dependencyMap.clear(((Integer )locations.elementAt(i)).intValue()); 2079 } 2080 } 2081 2082 2087 public void setTableProperties(Properties tableProperties) 2088 { 2089 this.tableProperties = tableProperties; 2090 } 2091 2092 2103 2104 public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, 2105 FromList fromListParam) 2106 throws StandardException 2107 { 2108 TableDescriptor tableDescriptor = bindTableDescriptor(); 2109 2110 if (tableDescriptor.getTableType() == TableDescriptor.VTI_TYPE) { 2111 ResultSetNode vtiNode = getNodeFactory().mapTableAsVTI( 2112 tableDescriptor, 2113 dataDictionary.getVTIClass(tableDescriptor), 2114 getCorrelationName(), 2115 resultColumns, 2116 getProperties(), 2117 getContextManager()); 2118 return vtiNode.bindNonVTITables(dataDictionary, fromListParam); 2119 } 2120 2121 ResultColumnList derivedRCL = resultColumns; 2122 2123 restrictionList = (PredicateList) getNodeFactory().getNode( 2125 C_NodeTypes.PREDICATE_LIST, 2126 getContextManager()); 2127 baseTableRestrictionList = (PredicateList) getNodeFactory().getNode( 2128 C_NodeTypes.PREDICATE_LIST, 2129 getContextManager()); 2130 2131 2132 CompilerContext compilerContext = getCompilerContext(); 2133 2134 2135 resultColumns = genResultColList(); 2136 templateColumns = resultColumns; 2137 2138 2139 if (tableDescriptor.getTableType() == TableDescriptor.VIEW_TYPE) 2140 { 2141 FromTable fsq; 2142 ResultSetNode rsn; 2143 ViewDescriptor vd; 2144 CreateViewNode cvn; 2145 SchemaDescriptor compSchema; 2146 SchemaDescriptor prevCompSchema; 2147 2148 2151 vd = dataDictionary.getViewDescriptor(tableDescriptor); 2152 2153 2159 compSchema = dataDictionary.getSchemaDescriptor(vd.getCompSchemaId(), null); 2160 2161 prevCompSchema = compilerContext.setCompilationSchema(compSchema); 2162 2163 try 2164 { 2165 2166 2167 compilerContext.createDependency(vd); 2168 2169 if (SanityManager.DEBUG) 2170 { 2171 SanityManager.ASSERT(vd != null, 2172 "vd not expected to be null for " + tableName); 2173 } 2174 2175 2179 LanguageConnectionContext lcc = getLanguageConnectionContext(); 2180 CompilerContext newCC = lcc.pushCompilerContext(); 2181 cvn = (CreateViewNode) 2182 QueryTreeNode.parseQueryText( 2183 newCC, 2184 vd.getViewText(), 2185 (DataValueDescriptor[])null, lcc); 2187 2188 lcc.popCompilerContext(newCC); 2189 2190 rsn = cvn.getParsedQueryExpression(); 2191 2192 2198 if (rsn.getResultColumns().containsAllResultColumn()) 2199 { 2200 resultColumns.setCountMismatchAllowed(true); 2201 } 2202 for (int i = 0; i < resultColumns.size(); i++) { 2213 ResultColumn rc = (ResultColumn) resultColumns.elementAt(i); 2214 if (rc.isPrivilegeCollectionRequired()) 2215 compilerContext.addRequiredColumnPriv( rc.getTableColumnDescriptor()); 2216 } 2217 2218 fsq = (FromTable) getNodeFactory().getNode( 2219 C_NodeTypes.FROM_SUBQUERY, 2220 rsn, 2221 (correlationName != null) ? 2222 correlationName : getOrigTableName().getTableName(), 2223 resultColumns, 2224 tableProperties, 2225 getContextManager()); 2226 fsq.setLevel(level); 2228 fsq.disablePrivilegeCollection(); 2235 fsq.setOrigTableName(this.getOrigTableName()); 2236 return fsq.bindNonVTITables(dataDictionary, fromListParam); 2237 } 2238 finally 2239 { 2240 compilerContext.setCompilationSchema(prevCompSchema); 2241 } 2242 } 2243 else 2244 { 2245 2246 compilerContext.createDependency(tableDescriptor); 2247 2248 2249 baseConglomerateDescriptor = 2250 tableDescriptor.getConglomerateDescriptor( 2251 tableDescriptor.getHeapConglomerateId() 2252 ); 2253 2254 2255 columnNames = resultColumns.getColumnNames(); 2256 2257 2260 if (derivedRCL != null) 2261 { 2262 resultColumns.propagateDCLInfo(derivedRCL, 2263 origTableName.getFullTableName()); 2264 } 2265 2266 2267 if (tableNumber == -1) tableNumber = compilerContext.getNextTableNumber(); 2269 } 2270 2271 return this; 2272 } 2273 2274 2287 protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch) 2288 throws StandardException 2289 { 2290 String ourSchemaName = getOrigTableName().getSchemaName(); 2292 String fullName = (schemaName != null) ? (schemaName + '.' + name) : name; 2293 2294 2299 if (exactMatch) 2300 { 2301 2302 if ((schemaName != null && ourSchemaName == null) || 2303 (schemaName == null && ourSchemaName != null)) 2304 { 2305 return null; 2306 } 2307 2308 if (getExposedName().equals(fullName)) 2309 { 2310 return this; 2311 } 2312 2313 return null; 2314 } 2315 2316 2326 if (getExposedName().equals(fullName)) 2328 { 2329 return this; 2330 } 2331 else if ((schemaName != null && ourSchemaName != null) || 2332 (schemaName == null && ourSchemaName == null)) 2333 { 2334 return null; 2335 } 2336 2337 if (schemaName != null && ourSchemaName == null) 2340 { 2341 if (tableName.equals(origTableName) && 2345 ! schemaName.equals(tableDescriptor.getSchemaDescriptor().getSchemaName())) 2346 { 2347 return null; 2348 } 2349 2350 if (! getExposedName().equals(name)) 2352 { 2353 return null; 2354 } 2355 2356 if (! getExposedName().equals(getOrigTableName().getTableName())) 2358 { 2359 return null; 2360 } 2361 2362 return this; 2363 } 2364 2365 2368 if (! getExposedName().equals(getOrigTableName().getSchemaName() + "." + name)) 2369 { 2370 return null; 2371 } 2372 2373 return this; 2374 } 2375 2376 2377 2385 private TableDescriptor bindTableDescriptor() 2386 throws StandardException 2387 { 2388 String schemaName = tableName.getSchemaName(); 2389 SchemaDescriptor sd = getSchemaDescriptor(schemaName); 2390 2391 tableDescriptor = getTableDescriptor(tableName.getTableName(), sd); 2392 if (tableDescriptor == null) 2393 { 2394 TableName synonymTab = resolveTableToSynonym(tableName); 2396 if (synonymTab == null) 2397 throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName); 2398 2399 tableName = synonymTab; 2400 sd = getSchemaDescriptor(tableName.getSchemaName()); 2401 2402 tableDescriptor = getTableDescriptor(synonymTab.getTableName(), sd); 2403 if (tableDescriptor == null) 2404 throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName); 2405 } 2406 2407 return tableDescriptor; 2408 } 2409 2410 2411 2420 public void bindExpressions(FromList fromListParam) 2421 throws StandardException 2422 { 2423 2427 } 2428 2429 2439 2440 public void bindResultColumns(FromList fromListParam) 2441 throws StandardException 2442 { 2443 2444 } 2445 2446 2459 2460 public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException 2461 { 2462 ResultColumn resultColumn = null; 2463 TableName columnsTableName; 2464 TableName exposedTableName; 2465 2466 columnsTableName = columnReference.getTableNameNode(); 2467 2468 if(columnsTableName != null) { 2469 if(columnsTableName.getSchemaName() == null && correlationName == null) 2470 columnsTableName.bind(this.getDataDictionary()); 2471 } 2472 2476 exposedTableName = getExposedTableName(); 2477 2478 if(exposedTableName.getSchemaName() == null && correlationName == null) 2479 exposedTableName.bind(this.getDataDictionary()); 2480 2485 if (columnsTableName == null || columnsTableName.equals(exposedTableName)) 2486 { 2487 resultColumn = resultColumns.getResultColumn(columnReference.getColumnName()); 2488 2489 if (resultColumn != null) 2490 { 2491 columnReference.setTableNumber(tableNumber); 2492 if (tableDescriptor != null) 2493 { 2494 FormatableBitSet referencedColumnMap = tableDescriptor.getReferencedColumnMap(); 2495 if (referencedColumnMap == null) 2496 referencedColumnMap = new FormatableBitSet( 2497 tableDescriptor.getNumberOfColumns() + 1); 2498 referencedColumnMap.set(resultColumn.getColumnPosition()); 2499 tableDescriptor.setReferencedColumnMap(referencedColumnMap); 2500 } 2501 } 2502 } 2503 2504 return resultColumn; 2505 } 2506 2507 2525 2526 public ResultSetNode preprocess(int numTables, 2527 GroupByList gbl, 2528 FromList fromList) 2529 throws StandardException 2530 { 2531 2532 referencedTableMap = new JBitSet(numTables); 2533 referencedTableMap.set(tableNumber); 2534 2535 return genProjectRestrict(numTables); 2536 } 2537 2538 2560 2561 protected ResultSetNode genProjectRestrict(int numTables) 2562 throws StandardException 2563 { 2564 2567 ResultColumnList prRCList = resultColumns; 2568 resultColumns = resultColumns.copyListAndObjects(); 2569 2570 2576 prRCList.genVirtualColumnNodes(this, resultColumns, false); 2577 2578 2581 prRCList.doProjection(); 2582 2583 2584 return (ResultSetNode) getNodeFactory().getNode( 2585 C_NodeTypes.PROJECT_RESTRICT_NODE, 2586 this, 2587 prRCList, 2588 null, 2589 null, 2590 null, 2591 null, 2592 null, 2593 getContextManager() ); 2594 } 2595 2596 2601 public ResultSetNode changeAccessPath() throws StandardException 2602 { 2603 ResultSetNode retval; 2604 AccessPath ap = getTrulyTheBestAccessPath(); 2605 ConglomerateDescriptor trulyTheBestConglomerateDescriptor = 2606 ap.getConglomerateDescriptor(); 2607 JoinStrategy trulyTheBestJoinStrategy = ap.getJoinStrategy(); 2608 Optimizer optimizer = ap.getOptimizer(); 2609 2610 optimizer.trace(Optimizer.CHANGING_ACCESS_PATH_FOR_TABLE, 2611 tableNumber, 0, 0.0, null); 2612 2613 if (SanityManager.DEBUG) 2614 { 2615 SanityManager.ASSERT( 2616 trulyTheBestConglomerateDescriptor != null, 2617 "Should only modify access path after conglomerate has been chosen."); 2618 } 2619 2620 2624 if (bulkFetch != UNSET) 2625 { 2626 if ( ! trulyTheBestJoinStrategy.bulkFetchOK()) 2627 { 2628 throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_WITH_JOIN_TYPE, 2629 trulyTheBestJoinStrategy.getName()); 2630 } 2631 else if (trulyTheBestJoinStrategy.ignoreBulkFetch()) 2633 { 2634 disableBulkFetch(); 2635 } 2636 else if (isOneRowResultSet()) 2638 { 2639 disableBulkFetch(); 2640 } 2641 } 2642 2643 if (bulkFetch == 1) 2645 { 2646 disableBulkFetch(); 2647 } 2648 2649 2653 restrictionList.removeRedundantPredicates(); 2654 2655 2659 storeRestrictionList = (PredicateList) getNodeFactory().getNode( 2660 C_NodeTypes.PREDICATE_LIST, 2661 getContextManager()); 2662 nonStoreRestrictionList = (PredicateList) getNodeFactory().getNode( 2663 C_NodeTypes.PREDICATE_LIST, 2664 getContextManager()); 2665 requalificationRestrictionList = 2666 (PredicateList) getNodeFactory().getNode( 2667 C_NodeTypes.PREDICATE_LIST, 2668 getContextManager()); 2669 trulyTheBestJoinStrategy.divideUpPredicateLists( 2670 this, 2671 restrictionList, 2672 storeRestrictionList, 2673 nonStoreRestrictionList, 2674 requalificationRestrictionList, 2675 getDataDictionary()); 2676 2677 2692 if (trulyTheBestJoinStrategy.bulkFetchOK() && 2693 !(trulyTheBestJoinStrategy.ignoreBulkFetch()) && 2694 ! bulkFetchTurnedOff && 2695 (bulkFetch == UNSET) && 2696 !forUpdate() && 2697 !isOneRowResultSet() && 2698 getLevel() == 0) 2699 { 2700 bulkFetch = getDefaultBulkFetch(); 2701 } 2702 2703 2704 getCompilerContext().createDependency( 2705 trulyTheBestConglomerateDescriptor); 2706 2707 2708 if ( ! trulyTheBestConglomerateDescriptor.isIndex()) 2709 { 2710 2719 boolean isSysstatements = tableName.equals("SYS","SYSSTATEMENTS"); 2720 2723 templateColumns = resultColumns; 2724 referencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, isSysstatements, false); 2725 resultColumns = resultColumns.compactColumns(cursorTargetTable, isSysstatements); 2726 return this; 2727 } 2728 2729 2730 2731 if (ap.getCoveringIndexScan() && (!cursorTargetTable())) 2732 { 2733 2734 resultColumns = newResultColumns(resultColumns, 2735 trulyTheBestConglomerateDescriptor, 2736 baseConglomerateDescriptor, 2737 false); 2738 2739 2743 templateColumns = newResultColumns(resultColumns, 2744 trulyTheBestConglomerateDescriptor, 2745 baseConglomerateDescriptor, 2746 false); 2747 templateColumns.addRCForRID(); 2748 2749 if (forUpdate()) 2751 { 2752 resultColumns.addRCForRID(); 2753 } 2754 2755 2760 referencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable,true, false); 2761 resultColumns = resultColumns.compactColumns(cursorTargetTable,true); 2762 2763 resultColumns.setIndexRow( 2764 baseConglomerateDescriptor.getConglomerateNumber(), 2765 forUpdate()); 2766 2767 return this; 2768 } 2769 2770 2773 getCompilerContext().createDependency(baseConglomerateDescriptor); 2774 2775 2779 if (bulkFetch != UNSET) 2780 { 2781 restrictionList.copyPredicatesToOtherList( 2782 requalificationRestrictionList); 2783 } 2784 2785 2793 ResultColumnList newResultColumns = 2794 newResultColumns(resultColumns, 2795 trulyTheBestConglomerateDescriptor, 2796 baseConglomerateDescriptor, 2797 true 2798 ); 2799 2800 2808 FormatableBitSet indexReferencedCols = null; 2810 FormatableBitSet heapReferencedCols = null; 2811 if ((bulkFetch == UNSET) && 2812 (requalificationRestrictionList == null || 2813 requalificationRestrictionList.size() == 0)) 2814 { 2815 2818 indexReferencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, true, false); 2819 heapReferencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, true, true); 2820 if (heapReferencedCols != null) 2821 { 2822 indexReferencedCols.xor(heapReferencedCols); 2823 } 2824 } 2825 else 2826 { 2827 heapReferencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, true, false) ; 2829 } 2830 ResultColumnList heapRCL = resultColumns.compactColumns(cursorTargetTable, false); 2831 retval = (ResultSetNode) getNodeFactory().getNode( 2832 C_NodeTypes.INDEX_TO_BASE_ROW_NODE, 2833 this, 2834 baseConglomerateDescriptor, 2835 heapRCL, 2836 new Boolean (cursorTargetTable), 2837 heapReferencedCols, 2838 indexReferencedCols, 2839 requalificationRestrictionList, 2840 new Boolean (forUpdate()), 2841 tableProperties, 2842 getContextManager()); 2843 2844 2848 resultColumns = newResultColumns; 2849 2850 templateColumns = newResultColumns(resultColumns, 2851 trulyTheBestConglomerateDescriptor, 2852 baseConglomerateDescriptor, 2853 false); 2854 2863 if (bulkFetch != UNSET) 2864 { 2865 resultColumns.markAllUnreferenced(); 2866 storeRestrictionList.markReferencedColumns(); 2867 if (nonStoreRestrictionList != null) 2868 { 2869 nonStoreRestrictionList.markReferencedColumns(); 2870 } 2871 } 2872 resultColumns.addRCForRID(); 2873 templateColumns.addRCForRID(); 2874 2875 referencedCols = resultColumns.getReferencedFormatableBitSet(cursorTargetTable, false, false); 2877 resultColumns = resultColumns.compactColumns(cursorTargetTable, false); 2878 resultColumns.setIndexRow( 2879 baseConglomerateDescriptor.getConglomerateNumber(), 2880 forUpdate()); 2881 2882 2885 getUpdateLocks = cursorTargetTable; 2886 cursorTargetTable = false; 2887 2888 return retval; 2889 } 2890 2891 2909 private ResultColumnList newResultColumns( 2910 ResultColumnList oldColumns, 2911 ConglomerateDescriptor idxCD, 2912 ConglomerateDescriptor heapCD, 2913 boolean cloneRCs) 2914 throws StandardException 2915 { 2916 IndexRowGenerator irg = idxCD.getIndexDescriptor(); 2917 int[] baseCols = irg.baseColumnPositions(); 2918 ResultColumnList newCols = 2919 (ResultColumnList) getNodeFactory().getNode( 2920 C_NodeTypes.RESULT_COLUMN_LIST, 2921 getContextManager()); 2922 2923 for (int i = 0; i < baseCols.length; i++) 2924 { 2925 int basePosition = baseCols[i]; 2926 ResultColumn oldCol = oldColumns.getResultColumn(basePosition); 2927 ResultColumn newCol; 2928 2929 if (SanityManager.DEBUG) 2930 { 2931 SanityManager.ASSERT(oldCol != null, 2932 "Couldn't find base column "+basePosition+ 2933 "\n. RCL is\n"+oldColumns); 2934 } 2935 2936 2942 if (cloneRCs) 2943 { 2944 newCol = oldCol.cloneMe(); 2945 oldCol.setExpression( 2946 (ValueNode) getNodeFactory().getNode( 2947 C_NodeTypes.VIRTUAL_COLUMN_NODE, 2948 this, 2949 newCol, 2950 ReuseFactory.getInteger(oldCol.getVirtualColumnId()), 2951 getContextManager())); 2952 } 2953 else 2954 { 2955 newCol = oldCol; 2956 } 2957 2958 newCols.addResultColumn(newCol); 2959 } 2960 2961 2968 newCols.setIndexRow(heapCD.getConglomerateNumber(), forUpdate()); 2969 2970 return newCols; 2971 } 2972 2973 2982 public void generate(ActivationClassBuilder acb, 2983 MethodBuilder mb) 2984 throws StandardException 2985 { 2986 generateResultSet( acb, mb ); 2987 2988 2992 if (cursorTargetTable) 2993 { 2994 acb.rememberCursorTarget(mb); 2995 } 2996 } 2997 2998 3007 public void generateResultSet(ExpressionClassBuilder acb, 3008 MethodBuilder mb) 3009 throws StandardException 3010 { 3011 3012 if (SanityManager.DEBUG) 3013 SanityManager.ASSERT( 3014 getTrulyTheBestAccessPath().getConglomerateDescriptor() != null); 3015 3016 3019 assignResultSetNumber(); 3020 3021 3025 if (specialMaxScan) 3026 { 3027 generateMaxSpecialResultSet(acb, mb); 3028 return; 3029 } 3030 3031 3035 if (distinctScan) 3036 { 3037 generateDistinctScan(acb, mb); 3038 return; 3039 } 3040 3041 3045 3046 if(raDependentScan) 3047 { 3048 generateRefActionDependentTableScan(acb, mb); 3049 return; 3050 3051 } 3052 3053 JoinStrategy trulyTheBestJoinStrategy = 3054 getTrulyTheBestAccessPath().getJoinStrategy(); 3055 3056 acb.pushGetResultSetFactoryExpression(mb); 3058 3059 int nargs = getScanArguments(acb, mb); 3060 3061 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, 3062 trulyTheBestJoinStrategy.resultSetMethodName(bulkFetch != UNSET), 3063 ClassName.NoPutResultSet, nargs); 3064 3065 3077 if ((updateOrDelete == UPDATE) || (updateOrDelete == DELETE)) 3078 { 3079 mb.cast(ClassName.CursorResultSet); 3080 mb.putField(acb.getRowLocationScanResultSetName(), ClassName.CursorResultSet); 3081 mb.cast(ClassName.NoPutResultSet); 3082 } 3083 } 3084 3085 3090 public CostEstimate getFinalCostEstimate() 3091 { 3092 return getTrulyTheBestAccessPath().getCostEstimate(); 3093 } 3094 3095 3102 private void pushIndexName(ConglomerateDescriptor cd, MethodBuilder mb) 3103 throws StandardException 3104 { 3105 if (cd.isConstraint()) { 3106 DataDictionary dd = getDataDictionary(); 3107 ConstraintDescriptor constraintDesc = 3108 dd.getConstraintDescriptor(tableDescriptor, cd.getUUID()); 3109 mb.push(constraintDesc.getConstraintName()); 3110 } else if (cd.isIndex()) { 3111 mb.push(cd.getConglomerateName()); 3112 } else { 3113 mb.pushNull("java.lang.String"); 3117 } 3118 } 3119 3120 private void generateMaxSpecialResultSet 3121 ( 3122 ExpressionClassBuilder acb, 3123 MethodBuilder mb 3124 ) throws StandardException 3125 { 3126 ConglomerateDescriptor cd = getTrulyTheBestAccessPath().getConglomerateDescriptor(); 3127 CostEstimate costEstimate = getFinalCostEstimate(); 3128 int colRefItem = (referencedCols == null) ? 3129 -1 : 3130 acb.addItem(referencedCols); 3131 boolean tableLockGranularity = tableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY; 3132 3133 3151 3152 acb.pushGetResultSetFactoryExpression(mb); 3153 3154 acb.pushThisAsActivation(mb); 3155 mb.push(getResultSetNumber()); 3156 resultColumns.generateHolder(acb, mb, referencedCols, (FormatableBitSet) null); 3157 mb.push(cd.getConglomerateNumber()); 3158 mb.push(tableDescriptor.getName()); 3159 if (tableProperties != null) 3163 mb.push(org.apache.derby.iapi.util.PropertyUtil.sortProperties(tableProperties)); 3164 else 3165 mb.pushNull("java.lang.String"); 3166 pushIndexName(cd, mb); 3167 mb.push(colRefItem); 3168 mb.push(getTrulyTheBestAccessPath().getLockMode()); 3169 mb.push(tableLockGranularity); 3170 mb.push(getCompilerContext().getScanIsolationLevel()); 3171 mb.push(costEstimate.singleScanRowCount()); 3172 mb.push(costEstimate.getEstimatedCost()); 3173 3174 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getLastIndexKeyResultSet", 3175 ClassName.NoPutResultSet, 13); 3176 3177 3178 } 3179 3180 private void generateDistinctScan 3181 ( 3182 ExpressionClassBuilder acb, 3183 MethodBuilder mb 3184 ) throws StandardException 3185 { 3186 ConglomerateDescriptor cd = getTrulyTheBestAccessPath().getConglomerateDescriptor(); 3187 CostEstimate costEstimate = getFinalCostEstimate(); 3188 int colRefItem = (referencedCols == null) ? 3189 -1 : 3190 acb.addItem(referencedCols); 3191 boolean tableLockGranularity = tableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY; 3192 3193 3212 3213 3214 int[] hashKeyColumns; 3215 3216 hashKeyColumns = new int[resultColumns.size()]; 3217 if (referencedCols == null) 3218 { 3219 for (int index = 0; index < hashKeyColumns.length; index++) 3220 { 3221 hashKeyColumns[index] = index; 3222 } 3223 } 3224 else 3225 { 3226 int index = 0; 3227 for (int colNum = referencedCols.anySetBit(); 3228 colNum != -1; 3229 colNum = referencedCols.anySetBit(colNum)) 3230 { 3231 hashKeyColumns[index++] = colNum; 3232 } 3233 } 3234 3235 FormatableIntHolder[] fihArray = 3236 FormatableIntHolder.getFormatableIntHolders(hashKeyColumns); 3237 FormatableArrayHolder hashKeyHolder = new FormatableArrayHolder(fihArray); 3238 int hashKeyItem = acb.addItem(hashKeyHolder); 3239 long conglomNumber = cd.getConglomerateNumber(); 3240 StaticCompiledOpenConglomInfo scoci = getLanguageConnectionContext(). 3241 getTransactionCompile(). 3242 getStaticCompiledConglomInfo(conglomNumber); 3243 3244 acb.pushGetResultSetFactoryExpression(mb); 3245 3246 acb.pushThisAsActivation(mb); 3247 mb.push(conglomNumber); 3248 mb.push(acb.addItem(scoci)); 3249 resultColumns.generateHolder(acb, mb, referencedCols, (FormatableBitSet) null); 3250 mb.push(getResultSetNumber()); 3251 mb.push(hashKeyItem); 3252 mb.push(tableDescriptor.getName()); 3253 if (tableProperties != null) 3257 mb.push(org.apache.derby.iapi.util.PropertyUtil.sortProperties(tableProperties)); 3258 else 3259 mb.pushNull("java.lang.String"); 3260 pushIndexName(cd, mb); 3261 mb.push(cd.isConstraint()); 3262 mb.push(colRefItem); 3263 mb.push(getTrulyTheBestAccessPath().getLockMode()); 3264 mb.push(tableLockGranularity); 3265 mb.push(getCompilerContext().getScanIsolationLevel()); 3266 mb.push(costEstimate.singleScanRowCount()); 3267 mb.push(costEstimate.getEstimatedCost()); 3268 3269 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getDistinctScanResultSet", 3270 ClassName.NoPutResultSet, 16); 3271 } 3272 3273 3274 3282 3283 private void generateRefActionDependentTableScan 3284 ( 3285 ExpressionClassBuilder acb, 3286 MethodBuilder mb 3287 ) throws StandardException 3288 { 3289 3290 acb.pushGetResultSetFactoryExpression(mb); 3291 3292 int nargs = getScanArguments(acb, mb); 3294 3295 mb.push(raParentResultSetId); mb.push(fkIndexConglomId); 3298 mb.push(acb.addItem(fkColArray)); 3299 mb.push(acb.addItem(getDataDictionary().getRowLocationTemplate( 3300 getLanguageConnectionContext(), tableDescriptor))); 3301 3302 int argCount = nargs + 4; 3303 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getRaDependentTableScanResultSet", 3304 ClassName.NoPutResultSet, argCount); 3305 3306 if ((updateOrDelete == UPDATE) || (updateOrDelete == DELETE)) 3307 { 3308 mb.cast(ClassName.CursorResultSet); 3309 mb.putField(acb.getRowLocationScanResultSetName(), ClassName.CursorResultSet); 3310 mb.cast(ClassName.NoPutResultSet); 3311 } 3312 3313 } 3314 3315 3316 3317 private int getScanArguments(ExpressionClassBuilder acb, 3318 MethodBuilder mb) 3319 throws StandardException 3320 { 3321 MethodBuilder resultRowAllocator = 3323 resultColumns.generateHolderMethod(acb, 3324 referencedCols, 3325 (FormatableBitSet) null); 3326 3327 int colRefItem = -1; 3330 if (referencedCols != null) 3331 { 3332 colRefItem = acb.addItem(referencedCols); 3333 } 3334 3335 int indexColItem = -1; 3337 if (cursorTargetTable || getUpdateLocks) 3338 { 3339 ConglomerateDescriptor cd = getTrulyTheBestAccessPath().getConglomerateDescriptor(); 3340 if (cd.isIndex()) 3341 { 3342 int[] baseColPos = cd.getIndexDescriptor().baseColumnPositions(); 3343 boolean[] isAscending = cd.getIndexDescriptor().isAscending(); 3344 int[] indexCols = new int[baseColPos.length]; 3345 for (int i = 0; i < indexCols.length; i++) 3346 indexCols[i] = isAscending[i] ? baseColPos[i] : -baseColPos[i]; 3347 indexColItem = acb.addItem(indexCols); 3348 } 3349 } 3350 3351 AccessPath ap = getTrulyTheBestAccessPath(); 3352 JoinStrategy trulyTheBestJoinStrategy = ap.getJoinStrategy(); 3353 3354 3357 if (SanityManager.DEBUG) 3358 { 3359 if ( ( ! trulyTheBestJoinStrategy.bulkFetchOK()) && 3360 (bulkFetch != UNSET)) 3361 { 3362 SanityManager.THROWASSERT("bulkFetch should not be set "+ 3363 "for the join strategy " + 3364 trulyTheBestJoinStrategy.getName()); 3365 } 3366 } 3367 3368 int nargs = trulyTheBestJoinStrategy.getScanArgs( 3369 getLanguageConnectionContext().getTransactionCompile(), 3370 mb, 3371 this, 3372 storeRestrictionList, 3373 nonStoreRestrictionList, 3374 acb, 3375 bulkFetch, 3376 resultRowAllocator, 3377 colRefItem, 3378 indexColItem, 3379 getTrulyTheBestAccessPath(). 3380 getLockMode(), 3381 (tableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY), 3382 getCompilerContext().getScanIsolationLevel(), 3383 ap.getOptimizer().getMaxMemoryPerTable() 3384 ); 3385 3386 return nargs; 3387 } 3388 3389 3396 private int mapAbsoluteToRelativeColumnPosition(int absolutePosition) 3397 { 3398 if (referencedCols == null) 3399 { 3400 return absolutePosition; 3401 } 3402 3403 3408 int setBitCtr = 0; 3409 int bitCtr = 0; 3410 for ( ; 3411 bitCtr < referencedCols.size() && bitCtr < absolutePosition; 3412 bitCtr++) 3413 { 3414 if (referencedCols.get(bitCtr)) 3415 { 3416 setBitCtr++; 3417 } 3418 } 3419 return setBitCtr; 3420 } 3421 3422 3429 public String getExposedName() 3430 { 3431 if (correlationName != null) 3432 return correlationName; 3433 else 3434 return getOrigTableName().getFullTableName(); 3435 } 3436 3437 3445 private TableName getExposedTableName() throws StandardException 3446 { 3447 if (correlationName != null) 3448 return makeTableName(null, correlationName); 3449 else 3450 return getOrigTableName(); 3451 } 3452 3453 3458 3459 public TableName getTableNameField() 3460 { 3461 return tableName; 3462 } 3463 3464 3476 public ResultColumnList getAllResultColumns(TableName allTableName) 3477 throws StandardException 3478 { 3479 return getResultColumnsForList(allTableName, resultColumns, 3480 getOrigTableName()); 3481 } 3482 3483 3492 public ResultColumnList genResultColList() 3493 throws StandardException 3494 { 3495 ResultColumnList rcList = null; 3496 ResultColumn resultColumn; 3497 ValueNode valueNode; 3498 ColumnDescriptor colDesc = null; 3499 TableName exposedName; 3500 3501 3505 exposedName = getExposedTableName(); 3506 3507 3508 rcList = (ResultColumnList) getNodeFactory().getNode( 3509 C_NodeTypes.RESULT_COLUMN_LIST, 3510 getContextManager()); 3511 ColumnDescriptorList cdl = tableDescriptor.getColumnDescriptorList(); 3512 int cdlSize = cdl.size(); 3513 3514 for (int index = 0; index < cdlSize; index++) 3515 { 3516 3517 colDesc = (ColumnDescriptor) cdl.elementAt(index); 3518 colDesc.setTableDescriptor(tableDescriptor); 3524 3525 valueNode = (ValueNode) getNodeFactory().getNode( 3526 C_NodeTypes.BASE_COLUMN_NODE, 3527 colDesc.getColumnName(), 3528 exposedName, 3529 colDesc.getType(), 3530 getContextManager()); 3531 resultColumn = (ResultColumn) getNodeFactory().getNode( 3532 C_NodeTypes.RESULT_COLUMN, 3533 colDesc, 3534 valueNode, 3535 getContextManager()); 3536 3537 3538 rcList.addResultColumn(resultColumn); 3539 } 3540 3541 return rcList; 3542 } 3543 3544 3557 public ResultColumnList addColsToList 3558 ( 3559 ResultColumnList inputRcl, 3560 FormatableBitSet colsWeWant 3561 ) 3562 throws StandardException 3563 { 3564 ResultColumnList rcList = null; 3565 ResultColumn resultColumn; 3566 ValueNode valueNode; 3567 ColumnDescriptor cd = null; 3568 TableName exposedName; 3569 3570 3574 exposedName = getExposedTableName(); 3575 3576 3577 ResultColumnList newRcl = (ResultColumnList) getNodeFactory().getNode( 3578 C_NodeTypes.RESULT_COLUMN_LIST, 3579 getContextManager()); 3580 ColumnDescriptorList cdl = tableDescriptor.getColumnDescriptorList(); 3581 int cdlSize = cdl.size(); 3582 3583 for (int index = 0; index < cdlSize; index++) 3584 { 3585 3586 cd = (ColumnDescriptor) cdl.elementAt(index); 3587 int position = cd.getPosition(); 3588 3589 if (!colsWeWant.get(position)) 3590 { 3591 continue; 3592 } 3593 3594 if ((resultColumn = inputRcl.getResultColumn(position)) == null) 3595 { 3596 valueNode = (ValueNode) getNodeFactory().getNode( 3597 C_NodeTypes.COLUMN_REFERENCE, 3598 cd.getColumnName(), 3599 exposedName, 3600 getContextManager()); 3601 resultColumn = (ResultColumn) getNodeFactory(). 3602 getNode( 3603 C_NodeTypes.RESULT_COLUMN, 3604 cd, 3605 valueNode, 3606 getContextManager()); 3607 } 3608 3609 3610 newRcl.addResultColumn(resultColumn); 3611 } 3612 3613 return newRcl; 3614 } 3615 3616 3621 public TableName getTableName() 3622 throws StandardException 3623 { 3624 TableName tn; 3625 3626 tn = super.getTableName(); 3627 3628 if(tn != null) { 3629 if(tn.getSchemaName() == null && 3630 correlationName == null) 3631 tn.bind(this.getDataDictionary()); 3632 } 3633 3634 return (tn != null ? tn : tableName); 3635 } 3636 3637 3641 public boolean markAsCursorTargetTable() 3642 { 3643 cursorTargetTable = true; 3644 return true; 3645 } 3646 3647 3653 protected boolean cursorTargetTable() 3654 { 3655 return cursorTargetTable; 3656 } 3657 3658 3665 void markUpdated(ResultColumnList updateColumns) 3666 { 3667 resultColumns.markUpdated(updateColumns); 3668 } 3669 3670 3680 public boolean referencesTarget(String name, boolean baseTable) 3681 throws StandardException 3682 { 3683 return baseTable && name.equals(getBaseTableName()); 3684 } 3685 3686 3693 public boolean referencesSessionSchema() 3694 throws StandardException 3695 { 3696 return isSessionSchema(tableDescriptor.getSchemaDescriptor()); 3698 } 3699 3700 3701 3711 public boolean isOneRowResultSet() throws StandardException 3712 { 3713 if (existsBaseTable) 3715 { 3716 return true; 3717 } 3718 3719 3727 AccessPath ap = getTrulyTheBestAccessPath(); 3728 JoinStrategy trulyTheBestJoinStrategy = ap.getJoinStrategy(); 3729 PredicateList pl; 3730 3731 if (trulyTheBestJoinStrategy.isHashJoin()) 3732 { 3733 pl = (PredicateList) getNodeFactory().getNode( 3734 C_NodeTypes.PREDICATE_LIST, 3735 getContextManager()); 3736 if (storeRestrictionList != null) 3737 { 3738 pl.nondestructiveAppend(storeRestrictionList); 3739 } 3740 if (nonStoreRestrictionList != null) 3741 { 3742 pl.nondestructiveAppend(nonStoreRestrictionList); 3743 } 3744 return isOneRowResultSet(pl); 3745 } 3746 else 3747 { 3748 return isOneRowResultSet(getTrulyTheBestAccessPath(). 3749 getConglomerateDescriptor(), 3750 restrictionList); 3751 } 3752 } 3753 3754 3757 public boolean isNotExists() 3758 { 3759 return isNotExists; 3760 } 3761 3762 public boolean isOneRowResultSet(OptimizablePredicateList predList) throws StandardException 3763 { 3764 ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors(); 3765 3766 for (int index = 0; index < cds.length; index++) 3767 { 3768 if (isOneRowResultSet(cds[index], predList)) 3769 { 3770 return true; 3771 } 3772 } 3773 3774 return false; 3775 } 3776 3777 3788 protected boolean supersetOfUniqueIndex(boolean[] eqCols) 3789 throws StandardException 3790 { 3791 ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors(); 3792 3793 3794 for (int index = 0; index < cds.length; index++) 3795 { 3796 ConglomerateDescriptor cd = cds[index]; 3797 3798 if (! cd.isIndex()) 3799 { 3800 continue; 3801 } 3802 IndexDescriptor id = cd.getIndexDescriptor(); 3803 3804 if (! id.isUnique()) 3805 { 3806 continue; 3807 } 3808 3809 int[] keyColumns = id.baseColumnPositions(); 3810 3811 int inner = 0; 3812 for ( ; inner < keyColumns.length; inner++) 3813 { 3814 if (! eqCols[keyColumns[inner]]) 3815 { 3816 break; 3817 } 3818 } 3819 3820 3821 if (inner == keyColumns.length) 3822 { 3823 return true; 3824 } 3825 } 3826 3827 return false; 3828 } 3829 3830 3842 protected boolean supersetOfUniqueIndex(JBitSet[] tableColMap) 3843 throws StandardException 3844 { 3845 ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors(); 3846 3847 3848 for (int index = 0; index < cds.length; index++) 3849 { 3850 ConglomerateDescriptor cd = cds[index]; 3851 3852 if (! cd.isIndex()) 3853 { 3854 continue; 3855 } 3856 IndexDescriptor id = cd.getIndexDescriptor(); 3857 3858 if (! id.isUnique()) 3859 { 3860 continue; 3861 } 3862 3863 int[] keyColumns = id.baseColumnPositions(); 3864 int numBits = tableColMap[0].size(); 3865 JBitSet keyMap = new JBitSet(numBits); 3866 JBitSet resMap = new JBitSet(numBits); 3867 3868 int inner = 0; 3869 for ( ; inner < keyColumns.length; inner++) 3870 { 3871 keyMap.set(keyColumns[inner]); 3872 } 3873 int table = 0; 3874 for ( ; table < tableColMap.length; table++) 3875 { 3876 resMap.setTo(tableColMap[table]); 3877 resMap.and(keyMap); 3878 if (keyMap.equals(resMap)) 3879 { 3880 tableColMap[table].set(0); 3881 return true; 3882 } 3883 } 3884 3885 } 3886 3887 return false; 3888 } 3889 3890 3912 public int updateTargetLockMode() 3913 { 3914 3920 if (getTrulyTheBestAccessPath().getConglomerateDescriptor().isIndex()) 3921 return TransactionController.MODE_RECORD; 3922 3923 3936 int isolationLevel = 3937 getLanguageConnectionContext().getCurrentIsolationLevel(); 3938 3939 3940 if ((isolationLevel != ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL) && 3941 (tableDescriptor.getLockGranularity() != 3942 TableDescriptor.TABLE_LOCK_GRANULARITY)) 3943 { 3944 int lockMode = getTrulyTheBestAccessPath().getLockMode(); 3945 if (lockMode != TransactionController.MODE_RECORD) 3946 lockMode = (lockMode & 0xff) << 16; 3947 else 3948 lockMode = 0; 3949 lockMode += TransactionController.MODE_RECORD; 3950 3951 return lockMode; 3952 } 3953 3954 3956 return getTrulyTheBestAccessPath().getLockMode(); 3957 } 3958 3959 3976 boolean isOrderedOn(ColumnReference[] crs, boolean permuteOrdering, Vector fbtVector) 3977 throws StandardException 3978 { 3979 3984 for (int index = 0; index < crs.length; index++) 3986 { 3987 if (crs[index].getTableNumber() != tableNumber) 3988 { 3989 return false; 3990 } 3991 } 3992 ConglomerateDescriptor cd = getTrulyTheBestAccessPath().getConglomerateDescriptor(); 3994 if (! cd.isIndex()) 3995 { 3996 return false; 3997 } 3998 3999 boolean isOrdered; 4001 if (permuteOrdering) 4002 { 4003 isOrdered = isOrdered(crs, cd); 4004 } 4005 else 4006 { 4007 isOrdered = isStrictlyOrdered(crs, cd); 4008 } 4009 4010 if (fbtVector != null) 4011 { 4012 fbtVector.addElement(this); 4013 } 4014 4015 return isOrdered; 4016 } 4017 4018 4021 void disableBulkFetch() 4022 { 4023 bulkFetchTurnedOff = true; 4024 bulkFetch = UNSET; 4025 } 4026 4027 4030 void doSpecialMaxScan() 4031 { 4032 if (SanityManager.DEBUG) 4033 { 4034 if ((restrictionList.size() != 0) || 4035 (storeRestrictionList.size() != 0) || 4036 (nonStoreRestrictionList.size() != 0)) 4037 { 4038 SanityManager.THROWASSERT("shouldn't be setting max special scan because there is a restriction"); 4039 } 4040 } 4041 specialMaxScan = true; 4042 } 4043 4044 4051 boolean isPossibleDistinctScan(Set distinctColumns) 4052 { 4053 if ((restrictionList != null && restrictionList.size() != 0)) { 4054 return false; 4055 } 4056 4057 HashSet columns = new HashSet (); 4058 for (int i = 0; i < resultColumns.size(); i++) { 4059 ResultColumn rc = (ResultColumn) resultColumns.elementAt(i); 4060 columns.add(rc.getExpression()); 4061 } 4062 4063 return columns.equals(distinctColumns); 4064 } 4065 4066 4069 void markForDistinctScan() 4070 { 4071 distinctScan = true; 4072 } 4073 4074 4075 4080 void markOrderingDependent() 4081 { 4082 4088 } 4089 4090 4100 private boolean isOrdered(ColumnReference[] crs, ConglomerateDescriptor cd) 4101 throws StandardException 4102 { 4103 4115 boolean[] matchedCRs = new boolean[crs.length]; 4116 4117 int nextKeyColumn = 0; 4118 int[] keyColumns = cd.getIndexDescriptor().baseColumnPositions(); 4119 4120 for ( ; nextKeyColumn < keyColumns.length; nextKeyColumn++) 4122 { 4123 boolean currMatch = false; 4124 for (int nextCR = 0; nextCR < crs.length; nextCR++) 4126 { 4127 if (crs[nextCR].getColumnNumber() == keyColumns[nextKeyColumn]) 4128 { 4129 matchedCRs[nextCR] = true; 4130 currMatch = true; 4131 break; 4132 } 4133 } 4134 4135 if (currMatch) 4137 { 4138 continue; 4139 } 4140 4141 if (! storeRestrictionList.hasOptimizableEqualityPredicate(this, keyColumns[nextKeyColumn], true)) 4143 { 4144 break; 4145 } 4146 } 4147 4148 4149 int numCRsMatched = 0; 4150 for (int nextCR = 0; nextCR < matchedCRs.length; nextCR++) 4151 { 4152 if (matchedCRs[nextCR]) 4153 { 4154 numCRsMatched++; 4155 } 4156 } 4157 4158 if (numCRsMatched == matchedCRs.length) 4159 { 4160 return true; 4161 } 4162 4163 4167 if (nextKeyColumn == keyColumns.length) 4168 { 4169 if (cd.getIndexDescriptor().isUnique()) 4170 { 4171 return true; 4172 } 4173 else 4174 { 4175 return false; 4176 } 4177 } 4178 else 4179 { 4180 return false; 4181 } 4182 } 4183 4184 4194 private boolean isStrictlyOrdered(ColumnReference[] crs, ConglomerateDescriptor cd) 4195 throws StandardException 4196 { 4197 4206 int nextCR = 0; 4207 int nextKeyColumn = 0; 4208 int[] keyColumns = cd.getIndexDescriptor().baseColumnPositions(); 4209 4210 for ( ; nextCR < crs.length; nextCR++) 4212 { 4213 4217 if (nextKeyColumn == keyColumns.length) 4218 { 4219 if (cd.getIndexDescriptor().isUnique()) 4220 { 4221 break; 4222 } 4223 else 4224 { 4225 return false; 4226 } 4227 } 4228 if (crs[nextCR].getColumnNumber() == keyColumns[nextKeyColumn]) 4229 { 4230 nextKeyColumn++; 4231 continue; 4232 } 4233 else 4234 { 4235 while (crs[nextCR].getColumnNumber() != keyColumns[nextKeyColumn]) 4236 { 4237 if (! storeRestrictionList.hasOptimizableEqualityPredicate(this, keyColumns[nextKeyColumn], true)) 4239 { 4240 return false; 4241 } 4242 4243 nextKeyColumn++; 4245 4246 4249 if (nextKeyColumn == keyColumns.length) 4250 { 4251 if (cd.getIndexDescriptor().isUnique()) 4252 { 4253 break; 4254 } 4255 else 4256 { 4257 return false; 4258 } 4259 } 4260 } 4261 } 4262 } 4263 return true; 4264 } 4265 4266 4269 private boolean isOneRowResultSet(ConglomerateDescriptor cd, 4270 OptimizablePredicateList predList) 4271 throws StandardException 4272 { 4273 if (predList == null) 4274 { 4275 return false; 4276 } 4277 4278 if (SanityManager.DEBUG) 4279 { 4280 if (! (predList instanceof PredicateList)) 4281 { 4282 SanityManager.THROWASSERT( 4283 "predList should be a PredicateList, but is a " + 4284 predList.getClass().getName() 4285 ); 4286 } 4287 } 4288 4289 PredicateList restrictionList = (PredicateList) predList; 4290 4291 if (! cd.isIndex()) 4292 { 4293 return false; 4294 } 4295 4296 IndexRowGenerator irg = 4297 cd.getIndexDescriptor(); 4298 4299 if (! irg.isUnique()) 4301 { 4302 return false; 4303 } 4304 4305 int[] baseColumnPositions = irg.baseColumnPositions(); 4306 4307 DataDictionary dd = getDataDictionary(); 4308 4309 for (int index = 0; index < baseColumnPositions.length; index++) 4311 { 4312 int curCol = baseColumnPositions[index]; 4314 4315 4318 if (! restrictionList.hasOptimizableEqualityPredicate(this, curCol, true)) 4319 { 4320 return false; 4321 } 4322 4323 } 4324 4325 return true; 4326 } 4327 4328 private int getDefaultBulkFetch() 4329 throws StandardException 4330 { 4331 int valInt; 4332 String valStr = PropertyUtil.getServiceProperty( 4333 getLanguageConnectionContext().getTransactionCompile(), 4334 LanguageProperties.BULK_FETCH_PROP, 4335 LanguageProperties.BULK_FETCH_DEFAULT); 4336 4337 valInt = getIntProperty(valStr, LanguageProperties.BULK_FETCH_PROP); 4338 4339 if (valInt <= 0) 4341 { 4342 throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_VALUE, 4343 String.valueOf(valInt)); 4344 } 4345 4346 4352 return (valInt <= 1) ? 4353 UNSET : valInt; 4354 } 4355 4356 private String getUserSpecifiedIndexName() 4357 { 4358 String retval = null; 4359 4360 if (tableProperties != null) 4361 { 4362 retval = tableProperties.getProperty("index"); 4363 } 4364 4365 return retval; 4366 } 4367 4368 4372 private StoreCostController getStoreCostController( 4373 ConglomerateDescriptor cd) 4374 throws StandardException 4375 { 4376 return getCompilerContext().getStoreCostController(cd.getConglomerateNumber()); 4377 } 4378 4379 private StoreCostController getBaseCostController() 4380 throws StandardException 4381 { 4382 return getStoreCostController(baseConglomerateDescriptor); 4383 } 4384 4385 private boolean gotRowCount = false; 4386 private long rowCount = 0; 4387 private long baseRowCount() throws StandardException 4388 { 4389 if (! gotRowCount) 4390 { 4391 StoreCostController scc = getBaseCostController(); 4392 rowCount = scc.getEstimatedRowCount(); 4393 gotRowCount = true; 4394 } 4395 4396 return rowCount; 4397 } 4398 4399 private DataValueDescriptor[] getRowTemplate( 4400 ConglomerateDescriptor cd, 4401 StoreCostController scc) 4402 throws StandardException 4403 { 4404 4408 if (! cd.isIndex()) 4409 return templateColumns.buildEmptyRow().getRowArray(); 4410 4411 4412 ExecRow emptyIndexRow = templateColumns.buildEmptyIndexRow( 4413 tableDescriptor, 4414 cd, 4415 scc, 4416 getDataDictionary()); 4417 4418 return emptyIndexRow.getRowArray(); 4419 } 4420 4421 private ConglomerateDescriptor getFirstConglom() 4422 throws StandardException 4423 { 4424 getConglomDescs(); 4425 return conglomDescs[0]; 4426 } 4427 4428 private ConglomerateDescriptor getNextConglom(ConglomerateDescriptor currCD) 4429 throws StandardException 4430 { 4431 int index = 0; 4432 4433 for ( ; index < conglomDescs.length; index++) 4434 { 4435 if (currCD == conglomDescs[index]) 4436 { 4437 break; 4438 } 4439 } 4440 4441 if (index < conglomDescs.length - 1) 4442 { 4443 return conglomDescs[index + 1]; 4444 } 4445 else 4446 { 4447 return null; 4448 } 4449 } 4450 4451 private void getConglomDescs() 4452 throws StandardException 4453 { 4454 if (conglomDescs == null) 4455 { 4456 conglomDescs = tableDescriptor.getConglomerateDescriptors(); 4457 } 4458 } 4459 4460 4461 4465 public void setRefActionInfo(long fkIndexConglomId, 4466 int[]fkColArray, 4467 String parentResultSetId, 4468 boolean dependentScan) 4469 { 4470 4471 4472 this.fkIndexConglomId = fkIndexConglomId; 4473 this.fkColArray = fkColArray; 4474 this.raParentResultSetId = parentResultSetId; 4475 this.raDependentScan = dependentScan; 4476 } 4477 4478 4479} 4480 | Popular Tags |