1 21 22 package org.apache.derby.impl.store.access.btree; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.iapi.services.sanity.SanityManager; 27 import org.apache.derby.iapi.services.io.Storable; 28 29 import org.apache.derby.iapi.error.StandardException; 30 31 import org.apache.derby.iapi.store.access.conglomerate.Conglomerate; 32 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; 33 import org.apache.derby.iapi.store.access.conglomerate.ScanManager; 34 import org.apache.derby.iapi.store.access.conglomerate.TransactionManager; 35 36 import org.apache.derby.iapi.store.access.ConglomerateController; 37 import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo; 38 import org.apache.derby.iapi.store.access.GenericScanController; 39 import org.apache.derby.iapi.store.access.Qualifier; 40 import org.apache.derby.iapi.store.access.RowUtil; 41 import org.apache.derby.iapi.store.access.ScanController; 42 import org.apache.derby.iapi.store.access.ScanInfo; 43 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo; 44 import org.apache.derby.iapi.store.access.TransactionController; 45 46 import org.apache.derby.iapi.store.raw.ContainerHandle; 47 import org.apache.derby.iapi.store.raw.FetchDescriptor; 48 import org.apache.derby.iapi.store.raw.LockingPolicy; 49 import org.apache.derby.iapi.store.raw.Page; 50 import org.apache.derby.iapi.store.raw.RecordHandle; 51 import org.apache.derby.iapi.store.raw.Transaction; 52 53 import org.apache.derby.iapi.types.DataValueDescriptor; 54 55 import org.apache.derby.iapi.types.RowLocation; 56 57 import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil; 58 import org.apache.derby.impl.store.access.conglomerate.TemplateRow; 59 60 import org.apache.derby.iapi.services.io.FormatableBitSet; 61 import org.apache.derby.iapi.store.access.BackingStoreHashtable; 62 63 74 75 public abstract class BTreeScan extends OpenBTree implements ScanManager 76 { 77 78 81 82 88 protected Transaction init_rawtran = null; 89 protected boolean init_forUpdate; 90 protected FormatableBitSet init_scanColumnList; 91 protected DataValueDescriptor[] init_template; 92 protected DataValueDescriptor[] init_startKeyValue; 93 protected int init_startSearchOperator = 0; 94 protected Qualifier init_qualifier[][] = null; 95 protected DataValueDescriptor[] init_stopKeyValue; 96 protected int init_stopSearchOperator = 0; 97 protected boolean init_hold; 98 99 100 103 protected FetchDescriptor init_fetchDesc; 104 105 106 112 protected FetchDescriptor init_lock_fetch_desc; 113 114 115 BTreeRowPosition scan_position; 116 117 118 122 protected boolean init_useUpdateLocks = false; 123 124 165 protected static final int SCAN_INIT = 1; 166 protected static final int SCAN_INPROGRESS = 2; 167 protected static final int SCAN_DONE = 3; 168 protected static final int SCAN_HOLD_INIT = 4; 169 protected static final int SCAN_HOLD_INPROGRESS = 5; 170 171 175 protected int scan_state = SCAN_INIT; 176 177 180 protected int stat_numpages_visited = 0; 181 protected int stat_numrows_visited = 0; 182 protected int stat_numrows_qualified = 0; 183 protected int stat_numdeleted_rows_visited = 0; 184 185 188 protected int lock_operation; 189 190 191 195 protected DataValueDescriptor[][] fetchNext_one_slot_array = 196 new DataValueDescriptor[1][]; 197 198 199 200 public BTreeScan() 201 { 202 } 203 204 207 208 215 abstract protected int fetchRows( 216 BTreeRowPosition pos, 217 DataValueDescriptor[][] row_array, 218 RowLocation[] rowloc_array, 219 BackingStoreHashtable hash_table, 220 long max_rowcnt, 221 int[] key_column_numbers) 222 throws StandardException; 223 224 225 233 private void initScanParams( 234 DataValueDescriptor[] startKeyValue, 235 int startSearchOperator, 236 Qualifier qualifier[][], 237 DataValueDescriptor[] stopKeyValue, 238 int stopSearchOperator) 239 throws StandardException 240 { 241 this.init_startKeyValue = startKeyValue; 243 if (RowUtil.isRowEmpty(this.init_startKeyValue)) 244 this.init_startKeyValue = null; 245 246 this.init_startSearchOperator = startSearchOperator; 248 249 if ((qualifier != null) && (qualifier .length == 0)) 251 qualifier = null; 252 this.init_qualifier = qualifier; 253 254 this.init_stopKeyValue = stopKeyValue; 256 if (RowUtil.isRowEmpty(this.init_stopKeyValue)) 257 this.init_stopKeyValue = null; 258 259 this.init_stopSearchOperator = stopSearchOperator; 261 262 scan_position = new BTreeRowPosition(); 265 266 scan_position.init(); 267 268 scan_position.current_lock_template = 269 new DataValueDescriptor[this.init_template.length]; 270 271 scan_position.current_lock_template[this.init_template.length - 1] = 272 scan_position.current_lock_row_loc = 273 (RowLocation) ((RowLocation) 274 init_template[init_template.length - 1]).cloneObject(); 275 276 if (SanityManager.DEBUG) 280 { 281 if (init_scanColumnList != null) 282 { 283 286 FormatableBitSet required_cols; 287 288 if (qualifier != null) 289 required_cols = RowUtil.getQualifierBitSet(qualifier); 290 else 291 required_cols = new FormatableBitSet(0); 292 293 if (this.init_startKeyValue != null) 295 { 296 required_cols.grow(this.init_startKeyValue.length); 297 for (int i = 0; i < this.init_startKeyValue.length; i++) 298 required_cols.set(i); 299 } 300 301 if (this.init_stopKeyValue != null) 302 { 303 required_cols.grow(this.init_stopKeyValue.length); 304 for (int i = 0; i < this.init_stopKeyValue.length; i++) 305 required_cols.set(i); 306 } 307 308 FormatableBitSet required_cols_and_scan_list = 309 (FormatableBitSet) required_cols.clone(); 310 311 required_cols_and_scan_list.and(init_scanColumnList); 312 313 required_cols.grow(init_scanColumnList.size()); 316 317 if (!required_cols_and_scan_list.equals(required_cols)) 318 { 319 SanityManager.THROWASSERT( 320 "Some column specified in a Btree " + 321 " qualifier/start/stop list is " + 322 "not represented in the scanColumnList." + 323 "\n:required_cols_and_scan_list = " + 324 required_cols_and_scan_list + 325 "\n;required_cols = " + required_cols + 326 "\n;init_scanColumnList = " + init_scanColumnList); 327 } 328 } 329 } 330 } 331 332 342 protected void positionAtStartForForwardScan( 343 BTreeRowPosition pos) 344 throws StandardException 345 { 346 boolean exact; 347 348 if (SanityManager.DEBUG) 350 { 351 SanityManager.ASSERT( 352 (scan_state == SCAN_INIT) || (scan_state == SCAN_HOLD_INIT)); 353 SanityManager.ASSERT(pos.current_rh == null); 354 SanityManager.ASSERT(pos.current_positionKey == null); 355 SanityManager.ASSERT(pos.current_scan_pageno == 0); 356 } 357 358 while (true) 365 { 366 ControlRow root = ControlRow.Get(this, BTree.ROOTPAGEID); 369 370 stat_numpages_visited += root.getLevel() + 1; 372 373 boolean need_previous_lock = true; 374 375 if (init_startKeyValue == null) 376 { 377 pos.current_leaf = (LeafControlRow) root.searchLeft(this); 379 380 pos.current_slot = ControlRow.CR_SLOT; 381 exact = false; 382 } 383 else 384 { 385 387 if (SanityManager.DEBUG) 388 SanityManager.ASSERT( 389 (init_startSearchOperator == ScanController.GE) || 390 (init_startSearchOperator == ScanController.GT)); 391 392 SearchParameters sp = new SearchParameters( 393 init_startKeyValue, 394 ((init_startSearchOperator == ScanController.GE) ? 395 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH : 396 SearchParameters.POSITION_RIGHT_OF_PARTIAL_KEY_MATCH), 397 init_template, this, false); 398 399 pos.current_leaf = (LeafControlRow) root.search(sp); 400 401 pos.current_slot = sp.resultSlot; 402 exact = sp.resultExact; 403 404 415 if (exact && init_startSearchOperator == ScanController.GE) 416 { 417 pos.current_slot--; 418 419 if (getConglomerate().nUniqueColumns < getConglomerate().nKeyFields) 430 { 431 need_previous_lock = false; 433 } 434 } 435 } 436 437 boolean latch_released = false; 438 if (need_previous_lock) 439 { 440 latch_released = 441 !this.getLockingPolicy().lockScanRow( 442 this, this.getConglomerate(), pos, 443 true, 444 init_lock_fetch_desc, 445 pos.current_lock_template, 446 pos.current_lock_row_loc, 447 true, init_forUpdate, 448 lock_operation); 449 } 450 else 451 { 452 455 latch_released = 456 !this.getLockingPolicy().lockScan( 457 pos.current_leaf, (ControlRow) null, false, lock_operation); } 462 463 if (SanityManager.DEBUG) 465 { 466 latch_released = 467 test_errors( 468 this, 469 "BTreeScan_positionAtStartPosition", true, 470 this.getLockingPolicy(), 471 pos.current_leaf, latch_released); 472 } 473 474 if (latch_released) 475 { 476 pos.current_leaf = null; 478 continue; 479 } 480 else 481 { 482 break; 484 } 485 } 486 487 this.scan_state = SCAN_INPROGRESS; 488 pos.current_scan_pageno = pos.current_leaf.page.getPageNumber(); 489 pos.current_slot = pos.current_slot; 490 491 if (SanityManager.DEBUG) 492 SanityManager.ASSERT(pos.current_leaf != null); 493 } 494 495 506 protected void positionAtStartForBackwardScan( 507 BTreeRowPosition pos) 508 throws StandardException 509 { 510 boolean exact; 511 512 if (SanityManager.DEBUG) 514 { 515 SanityManager.ASSERT( 516 (this.scan_state == SCAN_INIT) || 517 (this.scan_state == SCAN_HOLD_INIT)); 518 519 SanityManager.ASSERT(pos.current_rh == null); 520 SanityManager.ASSERT(pos.current_positionKey == null); 521 SanityManager.ASSERT(pos.current_scan_pageno == 0); 522 } 523 524 while (true) 531 { 532 ControlRow root = ControlRow.Get(this, BTree.ROOTPAGEID); 535 536 stat_numpages_visited += root.getLevel() + 1; 538 539 if (init_startKeyValue == null) 540 { 541 pos.current_leaf = (LeafControlRow) root.searchRight(this); 543 544 pos.current_slot = pos.current_leaf.page.recordCount(); 545 exact = false; 546 } 547 else 548 { 549 554 555 556 if (SanityManager.DEBUG) 557 SanityManager.ASSERT( 558 (init_startSearchOperator == ScanController.GE) || 559 (init_startSearchOperator == ScanController.GT)); 560 561 563 SearchParameters sp = new SearchParameters( 564 init_startKeyValue, 565 ((init_startSearchOperator == ScanController.GE) ? 566 SearchParameters.POSITION_RIGHT_OF_PARTIAL_KEY_MATCH : 567 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH), 568 init_template, this, false); 569 570 pos.current_leaf = (LeafControlRow) root.search(sp); 571 572 pos.current_slot = sp.resultSlot; 573 exact = sp.resultExact; 574 575 586 587 if (exact) 588 { 589 if (init_startSearchOperator == ScanController.GE) 591 { 592 pos.current_slot++; 595 } 596 else 597 { 598 if (SanityManager.DEBUG) 601 SanityManager.ASSERT( 602 init_startSearchOperator == ScanController.GT); 603 } 604 } 605 else 606 { 607 pos.current_slot++; 610 } 611 } 612 613 boolean latch_released = 614 !this.getLockingPolicy().lockScanRow( 615 this, this.getConglomerate(), pos, 616 true, 617 init_lock_fetch_desc, 618 pos.current_lock_template, 619 pos.current_lock_row_loc, 620 true, init_forUpdate, lock_operation); 621 622 if (SanityManager.DEBUG) 624 { 625 latch_released = 626 test_errors( 627 this, 628 "BTreeScan_positionAtStartPosition", true, 629 this.getLockingPolicy(), pos.current_leaf, latch_released); 630 } 631 632 if (latch_released) 633 { 634 pos.current_leaf = null; 636 continue; 637 } 638 else 639 { 640 break; 642 } 643 } 644 645 this.scan_state = SCAN_INPROGRESS; 646 pos.current_scan_pageno = pos.current_leaf.page.getPageNumber(); 647 648 if (SanityManager.DEBUG) 649 SanityManager.ASSERT(pos.current_leaf != null); 650 651 } 654 655 667 protected void positionAtNextPage( 668 BTreeRowPosition pos) 669 throws StandardException 670 { 671 if (SanityManager.DEBUG) 675 SanityManager.ASSERT(pos.current_scan_pageno != 0); 676 677 while (true) 678 { 679 if ((pos.next_leaf = 680 (LeafControlRow) pos.current_leaf.getRightSibling(this)) == null) 681 { 682 break; 683 } 684 685 boolean latch_released = 686 !this.getLockingPolicy().lockScan( 687 pos.next_leaf, 688 (LeafControlRow) null, false , 690 ConglomerateController.LOCK_READ); 692 if (SanityManager.DEBUG) 694 { 695 latch_released = 696 test_errors( 697 this, 698 "BTreeScan_positionAtNextPage", true, 699 this.getLockingPolicy(), pos.next_leaf, latch_released); 700 } 701 702 if (!latch_released) 703 { 704 break; 705 } 706 } 707 708 if (SanityManager.DEBUG) 711 { 712 if (pos.current_scan_pageno != pos.current_leaf.page.getPageNumber()) 713 SanityManager.THROWASSERT( 714 "pos.current_scan_pageno = " + pos.current_scan_pageno + 715 "pos.current_leaf = " + pos.current_leaf); 716 } 717 718 if (pos.current_rh != null) 720 { 721 this.getLockingPolicy().unlockScanRecordAfterRead( 722 pos, init_forUpdate); 723 } 724 725 this.getLockingPolicy().unlockScan( 726 pos.current_leaf.page.getPageNumber()); 727 pos.current_leaf.release(); 728 pos.current_leaf = pos.next_leaf; 729 730 pos.current_scan_pageno = 731 (pos.next_leaf == null) ? 0 : pos.next_leaf.page.getPageNumber(); 732 733 pos.current_slot = Page.FIRST_SLOT_NUMBER; 735 pos.current_rh = null; 736 } 737 738 747 abstract void positionAtStartPosition( 748 BTreeRowPosition pos) 749 throws StandardException; 750 751 752 759 protected void positionAtDoneScanFromClose( 760 BTreeRowPosition pos) 761 throws StandardException 762 { 763 773 if ((pos.current_rh != null) && !pos.current_rh_qualified) 774 { 775 if (pos.current_leaf == null || pos.current_leaf.page == null) 776 { 777 785 if (!reposition(pos, false)) 786 { 787 if (SanityManager.DEBUG) 788 { 789 SanityManager.THROWASSERT( 790 "can not fail while holding update row lock."); 791 } 792 } 793 794 this.getLockingPolicy().unlockScanRecordAfterRead( 795 pos, init_forUpdate); 796 797 pos.current_rh = null; 798 pos.current_leaf.release(); 799 pos.current_leaf = null; 800 } 801 } 802 803 804 if (pos.current_scan_pageno != 0) 812 { 813 this.getLockingPolicy().unlockScan(pos.current_scan_pageno); 814 pos.current_scan_pageno = 0; 815 } 816 817 pos.current_slot = Page.INVALID_SLOT_NUMBER; 818 pos.current_rh = null; 819 pos.current_positionKey = null; 820 this.scan_state = SCAN_DONE; 821 822 return; 823 } 824 825 837 protected void positionAtDoneScan( 838 BTreeRowPosition pos) 839 throws StandardException 840 { 841 842 if (pos.current_scan_pageno != 0) 850 { 851 this.getLockingPolicy().unlockScan(pos.current_scan_pageno); 852 pos.current_scan_pageno = 0; 853 } 854 855 pos.current_slot = Page.INVALID_SLOT_NUMBER; 856 pos.current_rh = null; 857 pos.current_positionKey = null; 858 this.scan_state = SCAN_DONE; 859 860 return; 861 } 862 863 864 878 protected boolean process_qualifier( 879 DataValueDescriptor[] row) 880 throws StandardException 881 { 882 boolean row_qualifies = true; 883 Qualifier q; 884 885 906 908 if (SanityManager.DEBUG) 909 { 910 SanityManager.ASSERT(this.init_qualifier != null); 912 SanityManager.ASSERT(this.init_qualifier.length > 0); 913 } 914 915 for (int i = 0; i < this.init_qualifier[0].length; i++) 916 { 917 919 row_qualifies = false; 920 921 923 q = this.init_qualifier[0][i]; 924 925 DataValueDescriptor columnValue = row[q.getColumnId()]; 928 929 row_qualifies = 930 columnValue.compare( 931 q.getOperator(), 932 q.getOrderable(), 933 q.getOrderedNulls(), 934 q.getUnknownRV()); 935 936 if (q.negateCompareResult()) 937 row_qualifies = !row_qualifies; 938 939 if (!row_qualifies) 941 return(false); 942 } 943 944 946 for (int and_idx = 1; and_idx < this.init_qualifier.length; and_idx++) 947 { 948 950 row_qualifies = false; 951 952 if (SanityManager.DEBUG) 953 { 954 SanityManager.ASSERT(this.init_qualifier[and_idx].length > 0); 956 } 957 958 for (int or_idx = 0; 959 or_idx < this.init_qualifier[and_idx].length; or_idx++) 960 { 961 963 q = this.init_qualifier[and_idx][or_idx]; 964 965 DataValueDescriptor columnValue = row[q.getColumnId()]; 968 969 row_qualifies = 970 columnValue.compare( 971 q.getOperator(), 972 q.getOrderable(), 973 q.getOrderedNulls(), 974 q.getUnknownRV()); 975 976 if (q.negateCompareResult()) 977 row_qualifies = !row_qualifies; 978 979 if (row_qualifies) 981 break; 982 } 983 984 if (!row_qualifies) 985 break; 986 } 987 988 return(row_qualifies); 989 } 990 991 992 1043 protected boolean reposition( 1044 BTreeRowPosition pos, 1045 boolean missing_row_for_key_ok) 1046 throws StandardException 1047 { 1048 1052 if (this.scan_state != SCAN_INPROGRESS) 1053 { 1054 throw StandardException.newException( 1055 SQLState.BTREE_SCAN_NOT_POSITIONED, 1056 new Integer (this.scan_state)); 1057 } 1058 1059 if (SanityManager.DEBUG) 1061 { 1062 if ((pos.current_rh == null) != (pos.current_positionKey != null)) 1063 SanityManager.THROWASSERT( 1064 "pos.current_rh = (" + pos.current_rh + "), " + 1065 "pos.current_positionKey = (" + 1066 pos.current_positionKey + ")."); 1067 } 1068 1069 if (!((pos.current_rh == null) == (pos.current_positionKey != null))) 1070 { 1071 throw StandardException.newException( 1072 SQLState.BTREE_SCAN_INTERNAL_ERROR, 1073 new Boolean (pos.current_rh == null), 1074 new Boolean (pos.current_positionKey == null)); 1075 } 1076 1077 if (pos.current_positionKey == null) 1078 { 1079 if (SanityManager.DEBUG) 1081 SanityManager.ASSERT(pos.current_scan_pageno != 0); 1082 1083 pos.current_leaf = (LeafControlRow) 1084 ControlRow.Get(this, pos.current_rh.getPageNumber()); 1085 pos.current_slot = 1086 pos.current_leaf.page.getSlotNumber(pos.current_rh); 1087 } 1088 else 1089 { 1090 if (SanityManager.DEBUG) 1094 SanityManager.ASSERT(pos.current_scan_pageno == 0); 1095 1096 SearchParameters sp = 1097 new SearchParameters( 1098 pos.current_positionKey, 1099 SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, 1101 init_template, this, false); 1102 1103 1106 1107 boolean latch_released; 1108 do 1109 { 1110 pos.current_leaf = (LeafControlRow) 1111 ControlRow.Get(this, BTree.ROOTPAGEID).search(sp); 1112 1113 if (sp.resultExact || missing_row_for_key_ok) 1114 { 1115 latch_released = 1124 !this.getLockingPolicy().lockScan( 1125 pos.current_leaf, 1126 (LeafControlRow) null, false , 1128 ConglomerateController.LOCK_READ); 1130 if (SanityManager.DEBUG) 1132 { 1133 latch_released = 1134 test_errors( 1135 this, 1136 "BTreeScan_reposition", true, 1137 this.getLockingPolicy(), 1138 pos.current_leaf, latch_released); 1139 } 1140 } 1141 else 1142 { 1143 1145 pos.current_leaf.release(); 1146 pos.current_leaf = null; 1147 return(false); 1148 } 1149 1150 } while (latch_released); 1151 1152 pos.current_scan_pageno = pos.current_leaf.page.getPageNumber(); 1153 pos.current_slot = sp.resultSlot; 1154 pos.current_positionKey = null; 1155 } 1156 1157 return(true); 1158 } 1159 1160 1163 1164 1165 1176 public void init( 1177 TransactionManager xact_manager, 1178 Transaction rawtran, 1179 boolean hold, 1180 int open_mode, 1181 int lock_level, 1182 BTreeLockingPolicy btree_locking_policy, 1183 FormatableBitSet scanColumnList, 1184 DataValueDescriptor[] startKeyValue, 1185 int startSearchOperator, 1186 Qualifier qualifier[][], 1187 DataValueDescriptor[] stopKeyValue, 1188 int stopSearchOperator, 1189 BTree conglomerate, 1190 LogicalUndo undo, 1191 StaticCompiledOpenConglomInfo static_info, 1192 DynamicCompiledOpenConglomInfo dynamic_info) 1193 throws StandardException 1194 { 1195 super.init( 1196 xact_manager, xact_manager, (ContainerHandle) null, rawtran, 1197 hold, 1198 open_mode, lock_level, btree_locking_policy, 1199 conglomerate, undo, dynamic_info); 1200 1201 1202 this.init_rawtran = rawtran; 1203 this.init_forUpdate = 1204 ((open_mode & ContainerHandle.MODE_FORUPDATE) == 1205 ContainerHandle.MODE_FORUPDATE); 1206 1207 this.init_useUpdateLocks = 1209 ((open_mode & 1210 ContainerHandle.MODE_USE_UPDATE_LOCKS) != 0); 1211 1212 this.init_hold = hold; 1213 1214 this.init_template = runtime_mem.get_template(); 1215 1216 this.init_scanColumnList = scanColumnList; 1217 1218 this.init_lock_fetch_desc = 1219 RowUtil.getFetchDescriptorConstant(init_template.length - 1); 1220 1221 if (SanityManager.DEBUG) 1222 { 1223 SanityManager.ASSERT( 1224 init_lock_fetch_desc.getMaxFetchColumnId() == 1225 (init_template.length - 1)); 1226 SanityManager.ASSERT( 1227 (init_lock_fetch_desc.getValidColumnsArray())[init_template.length - 1] == 1); 1228 } 1229 1230 this.init_fetchDesc = 1232 new FetchDescriptor( 1233 init_template.length, init_scanColumnList,(Qualifier[][]) null); 1234 1235 initScanParams( 1236 startKeyValue, startSearchOperator, 1237 qualifier, stopKeyValue, stopSearchOperator); 1238 1239 1240 if (SanityManager.DEBUG) 1241 { 1242 if (init_template != null) 1245 { 1246 SanityManager.ASSERT( 1247 TemplateRow.checkColumnTypes( 1248 this.getConglomerate().format_ids, init_template)); 1249 } 1250 } 1251 1252 1254 this.lock_operation = 1256 (init_forUpdate ? 1257 ConglomerateController.LOCK_UPD : 1258 ConglomerateController.LOCK_READ); 1259 1260 if (init_useUpdateLocks) 1261 this.lock_operation |= ConglomerateController.LOCK_UPDATE_LOCKS; 1262 1263 } 1265 1266 1267 1268 1271 1272 1275 public void close() 1276 throws StandardException 1277 { 1278 positionAtDoneScanFromClose(scan_position); 1280 1281 super.close(); 1282 1283 this.init_rawtran = null; 1285 this.init_template = null; 1286 this.init_startKeyValue = null; 1287 this.init_qualifier = null; 1288 this.init_stopKeyValue = null; 1289 1290 this.getXactMgr().closeMe(this); 1291 } 1292 1293 1299 public boolean delete() 1300 throws StandardException 1301 { 1302 boolean ret_val = false; 1303 1304 if (scan_state != SCAN_INPROGRESS) 1305 throw StandardException.newException( 1306 SQLState.AM_SCAN_NOT_POSITIONED); 1307 1308 if (SanityManager.DEBUG) 1309 { 1310 SanityManager.ASSERT(this.container != null, 1311 "BTreeScan.delete() called on a closed scan."); 1312 SanityManager.ASSERT(init_forUpdate); 1313 } 1314 1315 try 1316 { 1317 if (!reposition(scan_position, false)) 1319 { 1320 throw StandardException.newException( 1321 SQLState.AM_RECORD_NOT_FOUND, 1322 new Long (err_containerid), 1323 new Long (scan_position.current_rh.getId())); 1324 } 1325 1326 1327 if (init_useUpdateLocks) 1328 { 1329 1332 boolean latch_released = 1337 !this.getLockingPolicy().lockScanRow( 1338 this, this.getConglomerate(), scan_position, 1339 false, 1340 init_lock_fetch_desc, 1341 scan_position.current_lock_template, 1342 scan_position.current_lock_row_loc, 1343 false, init_forUpdate, lock_operation); 1344 1345 if (latch_released) 1346 { 1347 if (reposition(scan_position, false)) 1355 { 1356 throw StandardException.newException( 1357 SQLState.AM_RECORD_NOT_FOUND, 1358 new Long (err_containerid), 1359 new Long (scan_position.current_rh.getId())); 1360 } 1361 } 1362 } 1363 1364 1365 RecordHandle delete_rh = 1368 scan_position.current_leaf.page.fetchFromSlot( 1369 (RecordHandle) null, scan_position.current_slot, 1370 RowUtil.EMPTY_ROW, (FetchDescriptor) null, true); 1371 1372 ret_val = 1373 scan_position.current_leaf.page.delete( 1374 delete_rh, this.btree_undo); 1375 1376 1385 if (scan_position.current_leaf.page.nonDeletedRecordCount() == 1 && 1386 !(scan_position.current_leaf.getIsRoot() && 1387 scan_position.current_leaf.getLevel() == 0 )) 1388 { 1389 this.getXactMgr().addPostCommitWork(new BTreePostCommit( 1390 this.getXactMgr().getAccessManager(), 1391 this.getConglomerate(), 1392 scan_position.current_leaf.page.getPageNumber())); 1393 } 1394 } 1395 finally 1396 { 1397 if (scan_position.current_leaf != null) 1398 { 1399 scan_position.current_leaf.release(); 1401 scan_position.current_leaf = null; 1402 } 1403 } 1404 1405 return(ret_val); 1406 } 1407 1408 1425 public void didNotQualify() 1426 throws StandardException 1427 { 1428 } 1429 1430 1431 1452 public boolean doesCurrentPositionQualify() 1453 throws StandardException 1454 { 1455 if (scan_state != SCAN_INPROGRESS) 1456 throw StandardException.newException( 1457 SQLState.AM_SCAN_NOT_POSITIONED); 1458 1459 if (SanityManager.DEBUG) 1460 { 1461 SanityManager.ASSERT(this.container != null, 1462 "BTreeScan.doesCurrentPositionQualify() called on a closed scan."); 1463 } 1464 1465 try 1466 { 1467 if (!reposition(scan_position, false)) 1469 { 1470 1474 1479 return(false); 1480 } 1481 1482 if (SanityManager.DEBUG) 1483 { 1484 SanityManager.ASSERT( 1485 scan_position.current_leaf.page.fetchNumFieldsAtSlot( 1486 scan_position.current_slot) > 1); 1487 } 1488 1489 return( 1492 !scan_position.current_leaf.page.isDeletedAtSlot( 1493 scan_position.current_slot)); 1494 } 1495 finally 1496 { 1497 1498 if (scan_position.current_leaf != null) 1499 { 1500 scan_position.current_leaf.release(); 1502 scan_position.current_leaf = null; 1503 } 1504 } 1505 } 1506 1507 1508 1517 private void fetch(DataValueDescriptor[] row, boolean qualify) 1518 throws StandardException 1519 { 1520 if (scan_state != SCAN_INPROGRESS) 1521 throw StandardException.newException( 1522 SQLState.AM_SCAN_NOT_POSITIONED); 1523 if (SanityManager.DEBUG) 1524 { 1525 SanityManager.ASSERT(this.container != null, 1526 "BTreeScan.fetch() called on a closed scan."); 1527 1528 TemplateRow.checkPartialColumnTypes( 1529 this.getConglomerate().format_ids, 1530 init_scanColumnList, (int []) null, row); 1531 } 1532 1533 try 1534 { 1535 if (!reposition(scan_position, false)) 1537 { 1538 1542 throw StandardException.newException( 1543 SQLState.AM_RECORD_NOT_FOUND, 1544 new Long (err_containerid), 1545 new Long (scan_position.current_rh.getId())); 1546 } 1547 1548 if (SanityManager.DEBUG) 1549 { 1550 SanityManager.ASSERT( 1551 scan_position.current_leaf.page.fetchNumFieldsAtSlot( 1552 scan_position.current_slot) > 1); 1553 } 1554 1555 scan_position.current_rh = 1556 scan_position.current_leaf.page.fetchFromSlot( 1557 (RecordHandle) null, 1558 scan_position.current_slot, row, 1559 qualify ? init_fetchDesc : null, 1560 true); 1561 1562 1569 if (scan_position.current_leaf.page.isDeletedAtSlot( 1571 scan_position.current_slot)) 1572 { 1573 if (SanityManager.DEBUG) 1574 SanityManager.ASSERT(false, "positioned on deleted row"); 1575 } 1576 } 1577 finally 1578 { 1579 if (scan_position.current_leaf != null) 1580 { 1581 scan_position.current_leaf.release(); 1583 scan_position.current_leaf = null; 1584 } 1585 } 1586 1587 return; 1588 } 1589 1590 1596 public void fetch(DataValueDescriptor[] row) 1597 throws StandardException 1598 { 1599 fetch(row, true); 1600 } 1601 1602 1609 public void fetchWithoutQualify(DataValueDescriptor[] row) 1610 throws StandardException 1611 { 1612 fetch(row, false); 1613 } 1614 1615 1628 public ScanInfo getScanInfo() 1629 throws StandardException 1630 { 1631 return(new BTreeScanInfo(this)); 1632 } 1633 1634 1646 public boolean isCurrentPositionDeleted() 1647 throws StandardException 1648 { 1649 boolean ret_val; 1650 1651 if (scan_state != SCAN_INPROGRESS) 1652 throw StandardException.newException( 1653 SQLState.AM_SCAN_NOT_POSITIONED); 1654 1655 if (SanityManager.DEBUG) 1656 { 1657 SanityManager.ASSERT(this.container != null, 1658 "BTreeScan.isCurrentPositionDeleted() called on closed scan."); 1659 } 1660 try 1661 { 1662 1664 if (reposition(scan_position, false)) 1665 { 1666 1667 if (SanityManager.DEBUG) 1668 { 1669 SanityManager.ASSERT( 1670 scan_position.current_leaf.page.fetchNumFieldsAtSlot( 1671 scan_position.current_slot) > 1); 1672 } 1673 1674 ret_val = 1675 scan_position.current_leaf.page.isDeletedAtSlot( 1676 scan_position.current_slot); 1677 } 1678 else 1679 { 1680 ret_val = false; 1681 } 1682 } 1683 finally 1684 { 1685 if (scan_position.current_leaf != null) 1686 { 1687 scan_position.current_leaf.release(); 1689 scan_position.current_leaf = null; 1690 } 1691 } 1692 1693 return(ret_val); 1694 } 1695 1696 1702 public boolean isKeyed() 1703 { 1704 return(true); 1705 } 1706 1707 1712 public boolean positionAtRowLocation (RowLocation rLoc) 1713 throws StandardException 1714 { 1715 throw StandardException.newException( 1716 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 1717 } 1718 1719 1725 public boolean next() 1726 throws StandardException 1727 { 1728 fetchNext_one_slot_array[0] = runtime_mem.get_scratch_row(); 1730 boolean ret_val = 1731 fetchRows( 1732 scan_position, 1733 fetchNext_one_slot_array, 1734 (RowLocation[]) null, 1735 (BackingStoreHashtable) null, 1736 1, 1737 (int[]) null) == 1; 1738 1739 1740 return(ret_val); 1741 } 1742 1743 1769 public boolean fetchNext(DataValueDescriptor[] row) 1770 throws StandardException 1771 { 1772 boolean ret_val; 1773 1774 if (SanityManager.DEBUG) 1775 { 1776 TemplateRow.checkPartialColumnTypes( 1777 this.getConglomerate().format_ids, 1778 init_scanColumnList, (int[]) null, row); 1779 } 1780 1781 fetchNext_one_slot_array[0] = row; 1783 ret_val = 1784 fetchRows( 1785 scan_position, 1786 fetchNext_one_slot_array, 1787 (RowLocation[]) null, 1788 (BackingStoreHashtable) null, 1789 1, 1790 (int[]) null) == 1; 1791 1792 return(ret_val); 1793 } 1794 1795 1860 public int fetchNextGroup( 1861 DataValueDescriptor[][] row_array, 1862 RowLocation[] rowloc_array) 1863 throws StandardException 1864 { 1865 return( 1866 fetchRows( 1867 scan_position, 1868 row_array, 1869 rowloc_array, 1870 (BackingStoreHashtable) null, 1871 row_array.length, 1872 (int[]) null)); 1873 } 1874 1875 public int fetchNextGroup( 1876 DataValueDescriptor[][] row_array, 1877 RowLocation[] old_rowloc_array, 1878 RowLocation[] new_rowloc_array) 1879 throws StandardException 1880 { 1881 1884 throw StandardException.newException( 1885 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 1886 } 1887 1888 1995 public void fetchSet( 1996 long max_rowcnt, 1997 int[] key_column_numbers, 1998 BackingStoreHashtable hash_table) 1999 throws StandardException 2000 { 2001 2003 fetchRows( 2004 scan_position, 2005 (DataValueDescriptor[][]) null, 2006 (RowLocation[]) null, 2007 (BackingStoreHashtable) hash_table, 2008 max_rowcnt, 2009 key_column_numbers); 2010 2011 return; 2012 } 2013 2014 2015 2059 public final void reopenScan( 2060 DataValueDescriptor[] startKeyValue, 2061 int startSearchOperator, 2062 Qualifier qualifier[][], 2063 DataValueDescriptor[] stopKeyValue, 2064 int stopSearchOperator) 2065 throws StandardException 2066 { 2067 if (SanityManager.DEBUG) 2068 { 2069 if (!init_hold) 2070 SanityManager.ASSERT(this.container != null, 2071 "BTreeScan.reopenScan() called on non-held closed scan."); 2072 2073 SanityManager.ASSERT(scan_position.current_leaf == null); 2076 } 2077 2078 2083 if (scan_position.current_rh != null) 2084 { 2085 2087 if (!reposition(scan_position, false)) 2088 { 2089 if (SanityManager.DEBUG) 2090 { 2091 SanityManager.THROWASSERT( 2092 "can not fail while holding update row lock."); 2093 } 2094 } 2095 2096 this.getLockingPolicy().unlockScanRecordAfterRead( 2097 scan_position, init_forUpdate); 2098 2099 scan_position.current_rh = null; 2100 scan_position.current_leaf.release(); 2101 scan_position.current_leaf = null; 2102 } 2103 2104 2105 if (scan_position.current_scan_pageno != 0) 2113 { 2114 this.getLockingPolicy().unlockScan( 2115 scan_position.current_scan_pageno); 2116 scan_position.current_scan_pageno = 0; 2117 } 2118 2119 scan_position.current_slot = Page.INVALID_SLOT_NUMBER; 2120 scan_position.current_rh = null; 2121 scan_position.current_positionKey = null; 2122 2123 initScanParams( 2124 startKeyValue, startSearchOperator, 2125 qualifier, stopKeyValue, stopSearchOperator); 2126 2127 if (!init_hold) 2128 this.scan_state = SCAN_INIT; 2129 else 2130 this.scan_state = 2131 (this.container != null ? SCAN_INIT : SCAN_HOLD_INIT); 2132 } 2133 2134 2164 public void reopenScanByRowLocation( 2165 RowLocation startRowLocation, 2166 Qualifier qualifier[][]) 2167 throws StandardException 2168 { 2169 throw StandardException.newException( 2170 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 2171 } 2172 2173 2176 2177 2183 public void fetchLocation(RowLocation templateLocation) 2184 throws StandardException 2185 { 2186 throw StandardException.newException( 2187 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 2188 } 2189 2190 2197 public RowLocation newRowLocationTemplate() 2198 throws StandardException 2199 { 2200 throw StandardException.newException( 2201 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 2202 } 2203 2204 2212 public boolean replace(DataValueDescriptor[] row, FormatableBitSet validColumns) 2213 throws StandardException 2214 { 2215 throw StandardException.newException( 2216 SQLState.BTREE_UNIMPLEMENTED_FEATURE); 2217 } 2218 2219 2222 2223 2224 2227 public boolean closeForEndTransaction(boolean closeHeldScan) 2228 throws StandardException 2229 { 2230 if (!init_hold || closeHeldScan) 2231 { 2232 positionAtDoneScan(scan_position); 2234 2235 super.close(); 2236 2237 this.init_rawtran = null; 2239 this.init_template = null; 2240 this.init_startKeyValue = null; 2241 this.init_qualifier = null; 2242 this.init_stopKeyValue = null; 2243 2244 this.getXactMgr().closeMe(this); 2245 2246 return(true); 2247 } 2248 else 2249 { 2250 2251 if (this.scan_state == SCAN_INPROGRESS) 2252 { 2253 if (SanityManager.DEBUG) 2254 { 2255 SanityManager.ASSERT(scan_position != null); 2256 } 2257 2258 if (scan_position.current_positionKey == null) 2259 { 2260 2264 savePosition(); 2265 } 2266 this.scan_state = SCAN_HOLD_INPROGRESS; 2267 } 2268 else if (this.scan_state == SCAN_INIT) 2269 { 2270 this.scan_state = SCAN_HOLD_INIT; 2271 } 2272 2273 super.close(); 2274 2275 return(false); 2276 } 2277 } 2278 2279 2289 private void savePosition() 2290 throws StandardException 2291 { 2292 if (this.scan_state == SCAN_INPROGRESS) 2293 { 2294 if (SanityManager.DEBUG) 2296 { 2297 SanityManager.ASSERT( 2298 (scan_position.current_rh == null) == 2299 (scan_position.current_positionKey != null)); 2300 } 2301 2302 try 2303 { 2304 if (scan_position.current_rh != null) 2305 { 2306 2308 2310 if (reposition(scan_position, false)) 2311 { 2312 scan_position.current_positionKey = 2313 runtime_mem.get_row_for_export(); 2314 2315 2316 Page page = scan_position.current_leaf.getPage(); 2317 2318 2319 RecordHandle rh = 2320 page.fetchFromSlot( 2321 (RecordHandle) null, 2322 page.getSlotNumber(scan_position.current_rh), 2323 scan_position.current_positionKey, 2324 (FetchDescriptor) null, 2325 true); 2326 2327 if (SanityManager.DEBUG) 2328 { 2329 SanityManager.ASSERT(rh != null); 2330 } 2331 2332 scan_position.current_rh = null; 2333 scan_position.current_slot = Page.INVALID_SLOT_NUMBER; 2334 2335 2337 if (scan_position.current_scan_pageno != 0) 2338 { 2339 this.getLockingPolicy().unlockScan( 2340 scan_position.current_scan_pageno); 2341 scan_position.current_scan_pageno = 0; 2342 } 2343 2344 } 2345 else 2346 { 2347 2352 if (SanityManager.DEBUG) 2353 SanityManager.THROWASSERT( 2354 "Must always be able to reposition."); 2355 } 2356 } 2357 2358 } 2359 finally 2360 { 2361 2362 if (scan_position.current_leaf != null) 2363 { 2364 scan_position.current_leaf.release(); 2366 scan_position.current_leaf = null; 2367 } 2368 } 2369 } 2370 2371 } 2372 2373 2386 public void savePosition(Conglomerate conglom, Page page) 2387 throws StandardException 2388 { 2389 2393 2394 if (SanityManager.DEBUG) 2395 { 2396 SanityManager.ASSERT(page.isLatched()); 2397 } 2398 2399 2409 2410 2411 if ((this.getConglomerate() == conglom) && 2412 (this.scan_state == SCAN_INPROGRESS)) 2413 { 2414 if (SanityManager.DEBUG) 2416 { 2417 SanityManager.ASSERT( 2418 (scan_position.current_rh == null) == 2419 (scan_position.current_positionKey != null)); 2420 } 2421 2422 2432 2433 if (scan_position.current_rh != null && 2434 page.getPageNumber() == 2435 scan_position.current_rh.getPageNumber()) 2436 { 2437 scan_position.current_positionKey = 2438 runtime_mem.get_row_for_export(); 2439 2440 RecordHandle rh = 2441 page.fetchFromSlot( 2442 (RecordHandle) null, 2443 page.getSlotNumber(scan_position.current_rh), 2444 scan_position.current_positionKey, 2445 (FetchDescriptor) null, 2446 true); 2447 2448 if (SanityManager.DEBUG) 2449 { 2450 SanityManager.ASSERT(rh != null); 2451 } 2452 2453 scan_position.current_rh = null; 2454 scan_position.current_slot = Page.INVALID_SLOT_NUMBER; 2455 2456 2458 if (scan_position.current_scan_pageno != 0) 2459 { 2460 this.getLockingPolicy().unlockScan( 2461 scan_position.current_scan_pageno); 2462 scan_position.current_scan_pageno = 0; 2463 } 2464 } 2465 } 2466 } 2467 2468 public RecordHandle getCurrentRecordHandleForDebugging() 2469 { 2470 return(scan_position.current_rh); 2471 } 2472 2473 2476 public String toString() 2477 { 2478 if (SanityManager.DEBUG) 2479 { 2480 String string = 2481 "\n\tbtree = " + this.getConglomerate() + 2482 "\n\tscan direction = " + 2483 (this instanceof BTreeForwardScan ? "forward" : 2484 (this instanceof BTreeMaxScan ? "backward" : 2485 "illegal")) + 2486 "\n\t(scan_state:" + 2487 (this.scan_state == SCAN_INIT ? "SCAN_INIT" : 2488 this.scan_state == SCAN_INPROGRESS ? "SCAN_INPROGRESS" : 2489 this.scan_state == SCAN_DONE ? "SCAN_DONE" : 2490 this.scan_state == SCAN_HOLD_INIT ? "SCAN_HOLD_INIT" : 2491 this.scan_state == SCAN_HOLD_INPROGRESS ? "SCAN_HOLD_INPROGRESS" : 2492 "BAD_SCAN_STATE") + 2493 "\n\trh:" + scan_position.current_rh + 2494 "\n\tkey:" + scan_position.current_positionKey + ")" + 2495 "\n\tinit_rawtran = " + init_rawtran + 2496 "\n\tinit_hold = " + init_hold + 2497 "\n\tinit_forUpdate = " + init_forUpdate + 2498 "\n\tinit_useUpdateLocks = " + init_useUpdateLocks + 2499 "\n\tinit_scanColumnList = " + init_scanColumnList + 2500 "\n\tinit_scanColumnList.size() = "+ ( 2501 (init_scanColumnList != null ? 2502 init_scanColumnList.size() : 0)) + 2503 "\n\tinit_template = " + 2504 RowUtil.toString(init_template) + 2505 "\n\tinit_startKeyValue = " + 2506 RowUtil.toString(init_startKeyValue) + 2507 "\n\tinit_startSearchOperator = " + 2508 (init_startSearchOperator == ScanController.GE ? "GE" : 2509 (init_startSearchOperator == ScanController.GT ? "GT" : 2510 Integer.toString(init_startSearchOperator))) + 2511 "\n\tinit_qualifier[] = " + init_qualifier + 2512 "\n\tinit_stopKeyValue = " + 2513 RowUtil.toString(init_stopKeyValue) + 2514 "\n\tinit_stopSearchOperator = " + 2515 (init_stopSearchOperator == ScanController.GE ? "GE" : 2516 (init_stopSearchOperator == ScanController.GT ? "GT" : 2517 Integer.toString(init_stopSearchOperator))) + 2518 "\n\tstat_numpages_visited = " + 2519 stat_numpages_visited + 2520 "\n\tstat_numrows_visited = " + 2521 stat_numrows_visited + 2522 "\n\tstat_numrows_qualified = " + 2523 stat_numrows_qualified + 2524 "\n\tstat_numdeleted_rows_visited = " + 2525 stat_numdeleted_rows_visited ; 2526 2527 return(string); 2528 } 2529 else 2530 { 2531 return(null); 2532 } 2533 } 2534} 2535 | Popular Tags |