| 611 | } |
| 612 | |
| 613 | std::pair<std::vector<size_t>, NameSet> MergeTreeIndexGranuleText::matchTokens(const ColumnString & all_tokens, std::vector<std::string_view> needed_tokens) |
| 614 | { |
| 615 | NameSet missing_tokens; |
| 616 | std::vector<size_t> matched_indices; |
| 617 | matched_indices.reserve(needed_tokens.size()); |
| 618 | |
| 619 | size_t num_tokens = all_tokens.size(); |
| 620 | auto idx_range = collections::range(0, num_tokens); |
| 621 | auto it_begin = idx_range.begin(); |
| 622 | |
| 623 | /// Sort tokens lexicographically for correct binary search in the dictionary. |
| 624 | std::sort(needed_tokens.begin(), needed_tokens.end()); |
| 625 | |
| 626 | for (const auto & token : needed_tokens) |
| 627 | { |
| 628 | /// Use binary search to find indices of needed tokens in the block. |
| 629 | auto it = std::lower_bound(it_begin, idx_range.end(), token, [&all_tokens](size_t lhs_idx, std::string_view rhs_ref) |
| 630 | { |
| 631 | return all_tokens.getDataAt(lhs_idx) < rhs_ref; |
| 632 | }); |
| 633 | |
| 634 | it_begin = it; |
| 635 | size_t idx_in_block = it - idx_range.begin(); |
| 636 | |
| 637 | if (idx_in_block < num_tokens && all_tokens.getDataAt(idx_in_block) == token) |
| 638 | matched_indices.emplace_back(idx_in_block); |
| 639 | else |
| 640 | missing_tokens.insert(String(token)); |
| 641 | } |
| 642 | |
| 643 | return {std::move(matched_indices), std::move(missing_tokens)}; |
| 644 | } |
| 645 | |
| 646 | std::shared_ptr<TextIndexHeader> MergeTreeIndexGranuleText::loadHeader(MergeTreeIndexReaderStream & header_stream, MergeTreeIndexDeserializationState & state) |
| 647 | { |