1 21 22 package org.apache.derby.impl.sql.execute; 23 24 import org.apache.derby.iapi.services.loader.GeneratedMethod; 25 26 import org.apache.derby.iapi.services.monitor.Monitor; 27 28 import org.apache.derby.iapi.services.sanity.SanityManager; 29 30 import org.apache.derby.iapi.services.io.Storable; 31 32 import org.apache.derby.iapi.services.stream.HeaderPrintWriter; 33 import org.apache.derby.iapi.services.stream.InfoStreams; 34 35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 36 37 import org.apache.derby.iapi.error.StandardException; 38 import org.apache.derby.iapi.services.i18n.MessageService; 39 40 import org.apache.derby.iapi.reference.SQLState; 41 42 import org.apache.derby.iapi.sql.execute.CursorResultSet; 43 import org.apache.derby.iapi.sql.execute.ExecIndexRow; 44 import org.apache.derby.iapi.sql.execute.ExecRow; 45 import org.apache.derby.iapi.sql.execute.ExecutionContext; 46 import org.apache.derby.iapi.sql.execute.NoPutResultSet; 47 48 import org.apache.derby.iapi.sql.Activation; 49 import org.apache.derby.iapi.sql.ResultSet; 50 51 import org.apache.derby.iapi.store.access.ConglomerateController; 52 import org.apache.derby.iapi.store.access.Qualifier; 53 import org.apache.derby.iapi.store.access.RowUtil; 54 import org.apache.derby.iapi.store.access.ScanController; 55 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo; 56 import org.apache.derby.iapi.store.access.TransactionController; 57 58 import org.apache.derby.iapi.types.DataValueDescriptor; 59 60 import org.apache.derby.iapi.types.Orderable; 61 import org.apache.derby.iapi.types.RowLocation; 62 63 import org.apache.derby.iapi.store.access.BackingStoreHashtable; 64 import org.apache.derby.iapi.services.io.FormatableBitSet; 65 import org.apache.derby.iapi.services.io.FormatableArrayHolder; 66 import org.apache.derby.iapi.services.io.FormatableIntHolder; 67 import org.apache.derby.iapi.store.access.KeyHasher; 68 69 import java.util.Enumeration ; 70 import java.util.Properties ; 71 import java.util.Vector ; 72 73 83 public class HashScanResultSet extends NoPutResultSetImpl 84 implements CursorResultSet 85 { 86 private boolean hashtableBuilt; 87 private ExecIndexRow startPosition; 88 private ExecIndexRow stopPosition; 89 protected ExecRow candidate; protected ExecRow compactRow; 91 92 protected boolean firstNext = true; 94 private int numFetchedOnNext; 95 private int entryVectorSize; 96 private Vector entryVector; 97 98 private long conglomId; 101 protected StaticCompiledOpenConglomInfo scoci; 102 private GeneratedMethod resultRowAllocator; 103 private GeneratedMethod startKeyGetter; 104 private int startSearchOperator; 105 private GeneratedMethod stopKeyGetter; 106 private int stopSearchOperator; 107 public Qualifier[][] scanQualifiers; 108 public Qualifier[][] nextQualifiers; 109 private int initialCapacity; 110 private float loadFactor; 111 private int maxCapacity; 112 public String tableName; 113 public String userSuppliedOptimizerOverrides; 114 public String indexName; 115 public boolean forUpdate; 116 private boolean runTimeStatisticsOn; 117 private FormatableBitSet accessedCols; 118 public int isolationLevel; 119 public int lockMode; 120 public int[] keyColumns; 121 private boolean sameStartStopPosition; 122 private boolean skipNullKeyColumns; 123 124 protected BackingStoreHashtable hashtable; 125 protected boolean eliminateDuplicates; 127 public Properties scanProperties; 129 public String startPositionString; 130 public String stopPositionString; 131 public int hashtableSize; 132 public boolean isConstraint; 133 134 public static final int DEFAULT_INITIAL_CAPACITY = -1; 135 public static final float DEFAULT_LOADFACTOR = (float) -1.0; 136 public static final int DEFAULT_MAX_CAPACITY = -1; 137 138 139 HashScanResultSet(long conglomId, 143 StaticCompiledOpenConglomInfo scoci, Activation activation, 144 GeneratedMethod resultRowAllocator, 145 int resultSetNumber, 146 GeneratedMethod startKeyGetter, int startSearchOperator, 147 GeneratedMethod stopKeyGetter, int stopSearchOperator, 148 boolean sameStartStopPosition, 149 Qualifier[][] scanQualifiers, 150 Qualifier[][] nextQualifiers, 151 int initialCapacity, 152 float loadFactor, 153 int maxCapacity, 154 int hashKeyItem, 155 String tableName, 156 String userSuppliedOptimizerOverrides, 157 String indexName, 158 boolean isConstraint, 159 boolean forUpdate, 160 int colRefItem, 161 int lockMode, 162 boolean tableLocked, 163 int isolationLevel, 164 boolean skipNullKeyColumns, 165 double optimizerEstimatedRowCount, 166 double optimizerEstimatedCost) 167 throws StandardException 168 { 169 super(activation, 170 resultSetNumber, 171 optimizerEstimatedRowCount, 172 optimizerEstimatedCost); 173 this.scoci = scoci; 174 this.conglomId = conglomId; 175 176 if (SanityManager.DEBUG) { 177 SanityManager.ASSERT( activation!=null, "hash scan must get activation context"); 178 SanityManager.ASSERT( resultRowAllocator!= null, "hash scan must get row allocator"); 179 if (sameStartStopPosition) 180 { 181 SanityManager.ASSERT(stopKeyGetter == null, 182 "stopKeyGetter expected to be null when sameStartStopPosition is true"); 183 } 184 } 185 186 this.resultRowAllocator = resultRowAllocator; 187 188 this.startKeyGetter = startKeyGetter; 189 this.startSearchOperator = startSearchOperator; 190 this.stopKeyGetter = stopKeyGetter; 191 this.stopSearchOperator = stopSearchOperator; 192 this.sameStartStopPosition = sameStartStopPosition; 193 this.scanQualifiers = scanQualifiers; 194 this.nextQualifiers = nextQualifiers; 195 this.initialCapacity = initialCapacity; 196 this.loadFactor = loadFactor; 197 this.maxCapacity = maxCapacity; 198 this.tableName = tableName; 199 this.userSuppliedOptimizerOverrides = userSuppliedOptimizerOverrides; 200 this.indexName = indexName; 201 this.isConstraint = isConstraint; 202 this.forUpdate = forUpdate; 203 this.skipNullKeyColumns = skipNullKeyColumns; 204 205 206 FormatableArrayHolder fah = (FormatableArrayHolder) 207 (activation.getPreparedStatement(). 208 getSavedObject(hashKeyItem)); 209 FormatableIntHolder[] fihArray = (FormatableIntHolder[]) fah.getArray(FormatableIntHolder.class); 210 keyColumns = new int[fihArray.length]; 211 for (int index = 0; index < fihArray.length; index++) 212 { 213 keyColumns[index] = fihArray[index].getInt(); 214 } 215 216 this.accessedCols = null; 219 if (colRefItem != -1) 220 { 221 this.accessedCols = (FormatableBitSet)(activation.getPreparedStatement(). 222 getSavedObject(colRefItem)); 223 } 224 this.lockMode = lockMode; 225 226 227 if (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL) 229 { 230 isolationLevel = lcc.getCurrentIsolationLevel(); 231 } 232 233 if (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL) 234 { 235 this.isolationLevel = TransactionController.ISOLATION_SERIALIZABLE; 236 } 237 else 238 { 239 247 248 if (! tableLocked) 249 { 250 this.lockMode = TransactionController.MODE_RECORD; 251 } 252 253 if (isolationLevel == 254 ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) 255 { 256 this.isolationLevel = 257 TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK; 258 } 259 else if (isolationLevel == 260 ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) 261 { 262 this.isolationLevel = 263 TransactionController.ISOLATION_READ_UNCOMMITTED; 264 } 265 else if (isolationLevel == 266 ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) 267 { 268 this.isolationLevel = 269 TransactionController.ISOLATION_REPEATABLE_READ; 270 } 271 } 272 273 if (SanityManager.DEBUG) 274 { 275 SanityManager.ASSERT( 276 ((isolationLevel == 277 ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) || 278 (isolationLevel == 279 ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) || 280 (isolationLevel == 281 ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) || 282 (isolationLevel == 283 ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)), 284 285 "Invalid isolation level - " + isolationLevel); 286 } 287 288 runTimeStatisticsOn = 289 getLanguageConnectionContext().getRunTimeStatisticsMode(); 290 291 292 candidate = (ExecRow) resultRowAllocator.invoke(activation); 293 compactRow = 294 getCompactRow(candidate, accessedCols, (FormatableBitSet) null, false); 295 constructorTime += getElapsedMillis(beginTime); 296 } 297 298 302 309 public void openCore() throws StandardException 310 { 311 TransactionController tc; 312 313 beginTime = getCurrentTimeMillis(); 314 if (SanityManager.DEBUG) 315 SanityManager.ASSERT( ! isOpen, "HashScanResultSet already open"); 316 317 tc = activation.getTransactionController(); 319 320 if (startKeyGetter != null) 321 { 322 startPosition = (ExecIndexRow) startKeyGetter.invoke(activation); 323 if (sameStartStopPosition) 324 { 325 stopPosition = startPosition; 326 } 327 } 328 if (stopKeyGetter != null) 329 { 330 stopPosition = (ExecIndexRow) stopKeyGetter.invoke(activation); 331 } 332 333 if (skipScan(startPosition, stopPosition)) 337 { 338 ; 340 } 341 else if (! hashtableBuilt) 342 { 343 DataValueDescriptor[] startPositionRow = 344 startPosition == null ? null : startPosition.getRowArray(); 345 DataValueDescriptor[] stopPositionRow = 346 stopPosition == null ? null : stopPosition.getRowArray(); 347 348 hashtable = 349 tc.createBackingStoreHashtableFromScan( 350 conglomId, (forUpdate ? TransactionController.OPENMODE_FORUPDATE : 0), 352 lockMode, 353 isolationLevel, 354 accessedCols, 355 startPositionRow, 356 startSearchOperator, 357 scanQualifiers, 358 stopPositionRow, 359 stopSearchOperator, 360 -1, keyColumns, 362 eliminateDuplicates, -1, maxCapacity, 365 initialCapacity, loadFactor, runTimeStatisticsOn, 368 skipNullKeyColumns); 369 370 371 if (runTimeStatisticsOn) 372 { 373 hashtableSize = hashtable.size(); 374 375 if (scanProperties == null) 376 { 377 scanProperties = new Properties (); 378 } 379 380 try 381 { 382 if (hashtable != null) 383 { 384 hashtable.getAllRuntimeStats(scanProperties); 385 } 386 } 387 catch(StandardException se) 388 { 389 } 391 } 392 393 394 395 hashtableBuilt = true; 396 397 402 activation.informOfRowCount(this, (long) hashtableSize); 403 } 404 405 isOpen = true; 406 407 resetProbeVariables(); 408 409 numOpens++; 410 openTime += getElapsedMillis(beginTime); 411 } 412 413 418 public void reopenCore() throws StandardException { 419 TransactionController tc; 420 421 if (SanityManager.DEBUG) 422 { 423 SanityManager.ASSERT(isOpen, 424 "HashScanResultSet already open"); 425 } 426 427 beginTime = getCurrentTimeMillis(); 428 429 resetProbeVariables(); 430 431 numOpens++; 432 openTime += getElapsedMillis(beginTime); 433 } 434 435 private void resetProbeVariables() throws StandardException 436 { 437 firstNext = true; 438 numFetchedOnNext = 0; 439 entryVector = null; 440 entryVectorSize = 0; 441 442 if (nextQualifiers != null) 443 { 444 clearOrderableCache(nextQualifiers); 445 } 446 } 447 448 449 454 public ExecRow getNextRowCore() throws StandardException 455 { 456 ExecRow result = null; 457 DataValueDescriptor[] columns = null; 458 459 beginTime = getCurrentTimeMillis(); 460 if ( isOpen && hashtableBuilt) 461 { 462 467 do 468 { 469 if (firstNext) 470 { 471 firstNext = false; 472 473 477 Object hashEntry; 478 if (keyColumns.length == 1) 479 { 480 hashEntry = hashtable.get(nextQualifiers[0][0].getOrderable()); 481 } 482 else 483 { 484 KeyHasher mh = new KeyHasher(keyColumns.length); 485 486 if (SanityManager.DEBUG) 487 { 488 SanityManager.ASSERT(nextQualifiers.length == 1); 489 } 490 491 for (int index = 0; index < keyColumns.length; index++) 492 { 493 498 DataValueDescriptor dvd = 499 nextQualifiers[0][index].getOrderable(); 500 501 if (dvd == null) 502 { 503 mh = null; 504 break; 505 } 506 mh.setObject( 507 index, nextQualifiers[0][index].getOrderable()); 508 } 509 hashEntry = (mh == null) ? null : hashtable.get(mh); 510 } 511 512 if (hashEntry instanceof Vector ) 513 { 514 entryVector = (Vector ) hashEntry; 515 entryVectorSize = entryVector.size(); 516 columns = 517 (DataValueDescriptor[]) entryVector.firstElement(); 518 } 519 else 520 { 521 entryVector = null; 522 entryVectorSize = 0; 523 columns = (DataValueDescriptor[]) hashEntry; 524 } 525 } 526 else if (numFetchedOnNext < entryVectorSize) 527 { 528 531 columns = (DataValueDescriptor[]) 532 entryVector.elementAt(numFetchedOnNext); 533 } 534 535 if (columns != null) 536 { 537 if (SanityManager.DEBUG) 538 { 539 544 for (int i = 0; i < columns.length; i++) 546 { 547 if (columns[i] != null && 548 ! (columns[i] instanceof Storable)) 549 { 550 SanityManager.THROWASSERT( 551 "columns[" + i + "] expected to be Storable, not " + 552 columns[i].getClass().getName()); 553 } 554 } 555 } 556 557 559 572 573 if (RowUtil.qualifyRow(columns, nextQualifiers)) 574 { 575 setCompatRow(compactRow, columns); 576 577 rowsSeen++; 578 579 result = compactRow; 580 } 581 else 582 { 583 result = null; 584 } 585 586 numFetchedOnNext++; 587 } 588 else 589 { 590 result = null; 591 } 592 } 593 while (result == null && numFetchedOnNext < entryVectorSize); 594 595 } 596 597 currentRow = result; 598 setCurrentRow(result); 599 600 nextTime += getElapsedMillis(beginTime); 601 return result; 602 } 603 604 610 public void close() throws StandardException 611 { 612 beginTime = getCurrentTimeMillis(); 613 if ( isOpen ) 614 { 615 clearCurrentRow(); 620 621 if (hashtableBuilt) 622 { 623 scanProperties = getScanProperties(); 625 if (runTimeStatisticsOn) 627 { 628 startPositionString = printStartPosition(); 629 stopPositionString = printStopPosition(); 630 } 631 632 hashtable.close(); 634 hashtable = null; 635 hashtableBuilt = false; 636 } 637 startPosition = null; 638 stopPosition = null; 639 640 super.close(); 641 } 642 else 643 if (SanityManager.DEBUG) 644 SanityManager.DEBUG("CloseRepeatInfo","Close of HashScanResultSet repeated"); 645 646 closeTime += getElapsedMillis(beginTime); 647 } 648 649 657 public long getTimeSpent(int type) 658 { 659 long totTime = constructorTime + openTime + nextTime + closeTime; 660 661 662 if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY) 663 { 664 return totTime; 665 } 666 else 667 { 668 return totTime; 669 } 670 } 671 672 675 public int getScanIsolationLevel() 676 { 677 return isolationLevel; 678 } 679 680 683 public boolean requiresRelocking() 684 { 685 return( 687 ((isolationLevel == 688 TransactionController.ISOLATION_READ_COMMITTED) || 689 (isolationLevel == 690 TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK) || 691 (isolationLevel == 692 TransactionController.ISOLATION_READ_UNCOMMITTED))); 693 694 } 695 696 700 710 public RowLocation getRowLocation() throws StandardException 711 { 712 if (! isOpen) return null; 713 714 if ( ! hashtableBuilt) 715 return null; 716 717 720 if (SanityManager.DEBUG) 721 { 722 SanityManager.ASSERT(currentRow != null, 723 "There must be a current row when fetching the row location"); 724 Object rlCandidate = currentRow.getColumn( 725 currentRow.nColumns()); 726 if (! (rlCandidate instanceof RowLocation)) 727 { 728 SanityManager.THROWASSERT( 729 "rlCandidate expected to be instanceof RowLocation, not " + 730 rlCandidate.getClass().getName()); 731 } 732 } 733 734 return (RowLocation) currentRow.getColumn( 735 currentRow.nColumns()); 736 } 737 738 747 750 public ExecRow getCurrentRow() throws StandardException 751 { 752 755 if (SanityManager.DEBUG) 756 { 757 SanityManager.THROWASSERT( 758 "getCurrentRow() not expected to be called for HSRS"); 759 } 760 761 return null; 762 } 763 764 public String printStartPosition() 765 { 766 return printPosition(startSearchOperator, startKeyGetter, startPosition); 767 } 768 769 public String printStopPosition() 770 { 771 if (sameStartStopPosition) 772 { 773 return printPosition(stopSearchOperator, startKeyGetter, startPosition); 774 } 775 else 776 { 777 return printPosition(stopSearchOperator, stopKeyGetter, stopPosition); 778 } 779 } 780 781 784 private String printPosition(int searchOperator, 785 GeneratedMethod positionGetter, 786 ExecIndexRow eiRow) 787 { 788 String idt = ""; 789 790 String output = ""; 791 if (positionGetter == null) 792 { 793 return "\t" + 794 MessageService.getTextMessage(SQLState.LANG_NONE) + 795 "\n"; 796 } 797 798 ExecIndexRow positioner = null; 799 800 try 801 { 802 positioner = (ExecIndexRow) positionGetter.invoke(activation); 803 } 804 catch (StandardException e) 805 { 806 807 if (eiRow == null) 808 { 809 return "\t" + MessageService.getTextMessage( 810 SQLState.LANG_POSITION_NOT_AVAIL); 811 } 812 return "\t" + MessageService.getTextMessage( 813 SQLState.LANG_UNEXPECTED_EXC_GETTING_POSITIONER) + 814 "\n"; 815 } 816 817 if (positioner == null) 818 { 819 return "\t" + 820 MessageService.getTextMessage(SQLState.LANG_NONE) + 821 "\n"; 822 } 823 824 String searchOp = null; 825 826 switch (searchOperator) 827 { 828 case ScanController.GE: 829 searchOp = ">="; 830 break; 831 832 case ScanController.GT: 833 searchOp = ">"; 834 break; 835 836 default: 837 if (SanityManager.DEBUG) 838 { 839 SanityManager.THROWASSERT("Unknown search operator " + 840 searchOperator); 841 } 842 843 searchOp = "unknown value (" + searchOperator + ")"; 846 break; 847 } 848 849 output += "\t" + MessageService.getTextMessage( 850 SQLState.LANG_POSITIONER, 851 searchOp, 852 String.valueOf(positioner.nColumns())) 853 + "\n"; 854 855 output += "\t" + MessageService.getTextMessage( 856 SQLState.LANG_ORDERED_NULL_SEMANTICS) + 857 "\n"; 858 for (int position = 0; position < positioner.nColumns(); position++) 859 { 860 if (positioner.areNullsOrdered(position)) 861 { 862 output = output + position + " "; 863 } 864 } 865 866 return output + "\n"; 867 } 868 869 public Properties getScanProperties() 870 { 871 return scanProperties; 872 } 873 874 879 public boolean isForUpdate() 880 { 881 return forUpdate; 882 } 883 } 884 | Popular Tags |