| 620 | } |
| 621 | |
| 622 | UCHAR* IndexTableScan::openStream(thread_db* tdbb, Impure* impure, win* window) const |
| 623 | { |
| 624 | temporary_key* lower = impure->irsb_nav_current_lower; |
| 625 | temporary_key* upper = impure->irsb_nav_current_upper; |
| 626 | |
| 627 | setPage(tdbb, impure, NULL); |
| 628 | impure->irsb_nav_length = 0; |
| 629 | |
| 630 | // Find the starting leaf page |
| 631 | const IndexRetrieval* const retrieval = m_index->retrieval; |
| 632 | index_desc* const idx = (index_desc*) ((SCHAR*) impure + m_offset); |
| 633 | |
| 634 | Ods::btree_page* page = BTR_find_page(tdbb, retrieval, window, idx, lower, upper); |
| 635 | setPage(tdbb, impure, window); |
| 636 | |
| 637 | // find the upper limit for the search |
| 638 | temporary_key* limit_ptr = NULL; |
| 639 | if (retrieval->irb_upper_count) |
| 640 | { |
| 641 | // If upper key length is greater than declared key length, we need |
| 642 | // one "excess" byte for correct comparison. Without it there could |
| 643 | // be false equality hits. |
| 644 | impure->irsb_nav_upper_length = MIN(m_length + 1, upper->key_length); |
| 645 | memcpy(impure->irsb_nav_data + m_length, upper->key_data, impure->irsb_nav_upper_length); |
| 646 | } |
| 647 | |
| 648 | if (retrieval->irb_lower_count) |
| 649 | limit_ptr = lower; |
| 650 | |
| 651 | // If there is a starting descriptor, search down index to starting position. |
| 652 | // This may involve sibling buckets if splits are in progress. If there |
| 653 | // isn't a starting descriptor, walk down the left side of the index. |
| 654 | |
| 655 | if (limit_ptr) |
| 656 | { |
| 657 | UCHAR* pointer = NULL; |
| 658 | // If END_BUCKET is reached BTR_find_leaf will return NULL |
| 659 | while (!(pointer = BTR_find_leaf(page, limit_ptr, impure->irsb_nav_data, NULL, |
| 660 | (idx->idx_flags & idx_descending), |
| 661 | (retrieval->irb_generic & (irb_starting | irb_partial))))) |
| 662 | { |
| 663 | page = (Ods::btree_page*) CCH_HANDOFF(tdbb, window, page->btr_sibling, |
| 664 | LCK_read, pag_index); |
| 665 | } |
| 666 | |
| 667 | IndexNode node; |
| 668 | node.readNode(pointer, true); |
| 669 | |
| 670 | impure->irsb_nav_length = node.prefix + node.length; |
| 671 | return pointer; |
| 672 | } |
| 673 | |
| 674 | return page->btr_nodes + page->btr_jump_size; |
| 675 | } |
| 676 | |
| 677 | void IndexTableScan::setPage(thread_db* tdbb, Impure* impure, win* window) const |
| 678 | { |
nothing calls this directly
no test coverage detected