From 315d4d0aed4a0ed16308b5031b3594b7bd99fbcc Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Sat, 19 Jun 2021 16:52:27 +0530 Subject: [PATCH] Fix intersection on empty posting lists. --- src/posting_list.cpp | 29 +++++++++++++++++++++++++++++ test/posting_list_test.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/posting_list.cpp b/src/posting_list.cpp index 83b02eda..9eda281e 100644 --- a/src/posting_list.cpp +++ b/src/posting_list.cpp @@ -613,6 +613,20 @@ void posting_list_t::merge(const std::vector& posting_lists, st // Inspired by: https://stackoverflow.com/a/25509185/131050 void posting_list_t::intersect(const std::vector& posting_lists, std::vector& result_ids) { + if(posting_lists.empty()) { + return; + } + + if(posting_lists.size() == 1) { + auto it = posting_lists[0]->new_iterator(); + while(it.valid()) { + result_ids.push_back(it.id()); + it.next(); + } + + return ; + } + auto its = std::vector(); its.reserve(posting_lists.size()); @@ -650,6 +664,11 @@ void posting_list_t::intersect(const std::vector& posting_lists bool posting_list_t::block_intersect(const std::vector& posting_lists, const size_t batch_size, std::vector& its, result_iter_state_t& iter_state) { + + if(posting_lists.empty()) { + return false; + } + if(its.empty()) { its.reserve(posting_lists.size()); @@ -666,6 +685,16 @@ bool posting_list_t::block_intersect(const std::vector& posting size_t num_lists = its.size(); switch (num_lists) { + case 1: + while(its[0].valid()) { + iter_state.ids.push_back(its[0].id()); + its[0].next(); + + if(iter_state.ids.size() == batch_size) { + return its[0].valid(); + } + } + break; case 2: while(!at_end2(its)) { if(equals2(its)) { diff --git a/test/posting_list_test.cpp b/test/posting_list_test.cpp index 0644c0a2..ff10de7f 100644 --- a/test/posting_list_test.cpp +++ b/test/posting_list_test.cpp @@ -633,6 +633,38 @@ TEST(PostingListTest, IntersectionBasics) { ASSERT_FALSE(has_more); ASSERT_EQ(1, iter_state2.ids.size()); ASSERT_EQ(20, iter_state2.ids[0]); + + // single item itersection + std::vector single_item_list = {&p1}; + result_ids.clear(); + posting_list_t::intersect(single_item_list, result_ids); + std::vector expected_ids = {0, 2, 3, 20}; + ASSERT_EQ(expected_ids.size(), result_ids.size()); + + for(size_t i = 0; i < expected_ids.size(); i++) { + ASSERT_EQ(expected_ids[i], result_ids[i]); + } + + std::vector its3; + posting_list_t::result_iter_state_t iter_state3; + has_more = posting_list_t::block_intersect(single_item_list, 2, its3, iter_state3); + ASSERT_TRUE(has_more); + ASSERT_EQ(2, iter_state3.ids.size()); + has_more = posting_list_t::block_intersect(single_item_list, 2, its3, iter_state3); + ASSERT_FALSE(has_more); + ASSERT_EQ(2, iter_state3.ids.size()); + + // empty intersection list + std::vector empty_list; + result_ids.clear(); + posting_list_t::intersect(empty_list, result_ids); + ASSERT_EQ(0, result_ids.size()); + + std::vector its4; + posting_list_t::result_iter_state_t iter_state4; + has_more = posting_list_t::block_intersect(empty_list, 1, its4, iter_state4); + ASSERT_FALSE(has_more); + ASSERT_EQ(0, iter_state4.ids.size()); } TEST(PostingListTest, ResultsAndOffsetsBasics) {