diff options
author | Håvard Pettersen <havardpe@yahooinc.com> | 2022-10-25 10:53:41 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@yahooinc.com> | 2022-10-25 14:05:13 +0000 |
commit | 1c90a1aff5d166d1223edd00e82f9f7f3a64df48 (patch) | |
tree | 1fe8e7650ee3003d6f08b9fe59e8aa0c4eb2e7a1 /searchlib | |
parent | 70026cc89de5a1586f7b70e261d0f09c437a2263 (diff) |
use common algorithms for filter creation
add more testing
keep children blueprints in unique pointers
Diffstat (limited to 'searchlib')
19 files changed, 357 insertions, 375 deletions
diff --git a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp index 8e8327584a7..3c0b49da762 100644 --- a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp @@ -30,7 +30,7 @@ public: return mixChildrenFields(); } - virtual void sort(std::vector<Blueprint*> &children) const override { + virtual void sort(Children &children) const override { std::sort(children.begin(), children.end(), TieredGreaterEstimate()); } diff --git a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp index 2379213b87b..ef0fd56840a 100644 --- a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp @@ -56,6 +56,18 @@ bool got_global_filter(Blueprint &b) { return (static_cast<MyLeaf &>(b)).got_global_filter(); } +void check_sort_order(IntermediateBlueprint &self, std::vector<Blueprint*> unordered, std::vector<size_t> order) { + ASSERT_EQUAL(unordered.size(), order.size()); + std::vector<Blueprint::UP> children; + for (auto *child: unordered) { + children.push_back(std::unique_ptr<Blueprint>(child)); + } + self.sort(children); + for (size_t i = 0; i < children.size(); ++i) { + EXPECT_EQUAL(children[i].get(), unordered[order[i]]); + } +} + TEST("test AndNot Blueprint") { AndNotBlueprint b; { // combine @@ -86,20 +98,12 @@ TEST("test AndNot Blueprint") { EXPECT_EQUAL(true, got_global_filter(a.getChild(1))); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(10).create()); - Blueprint::UP c2 = ap(MyLeafSpec(20).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c1.get(), children[0]); - EXPECT_EQUAL(c3.get(), children[1]); - EXPECT_EQUAL(c4.get(), children[2]); - EXPECT_EQUAL(c2.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(10).create(), + MyLeafSpec(20).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {0, 2, 3, 1}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -161,20 +165,12 @@ TEST("test And Blueprint") { EXPECT_EQUAL(true, got_global_filter(a.getChild(1))); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(20).create()); - Blueprint::UP c2 = ap(MyLeafSpec(40).create()); - Blueprint::UP c3 = ap(MyLeafSpec(10).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c3.get(), children[0]); - EXPECT_EQUAL(c1.get(), children[1]); - EXPECT_EQUAL(c4.get(), children[2]); - EXPECT_EQUAL(c2.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(20).create(), + MyLeafSpec(40).create(), + MyLeafSpec(10).create(), + MyLeafSpec(30).create()}, + {2, 0, 3, 1}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -241,20 +237,12 @@ TEST("test Or Blueprint") { EXPECT_EQUAL(true, got_global_filter(o.getChild(o.childCnt() - 1))); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(10).create()); - Blueprint::UP c2 = ap(MyLeafSpec(20).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c3.get(), children[0]); - EXPECT_EQUAL(c4.get(), children[1]); - EXPECT_EQUAL(c2.get(), children[2]); - EXPECT_EQUAL(c1.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(10).create(), + MyLeafSpec(20).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {2, 3, 1, 0}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -290,20 +278,12 @@ TEST("test Near Blueprint") { EXPECT_EQUAL(0u, a.exposeFields().size()); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(40).create()); - Blueprint::UP c2 = ap(MyLeafSpec(10).create()); - Blueprint::UP c3 = ap(MyLeafSpec(30).create()); - Blueprint::UP c4 = ap(MyLeafSpec(20).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c2.get(), children[0]); - EXPECT_EQUAL(c4.get(), children[1]); - EXPECT_EQUAL(c3.get(), children[2]); - EXPECT_EQUAL(c1.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(40).create(), + MyLeafSpec(10).create(), + MyLeafSpec(30).create(), + MyLeafSpec(20).create()}, + {1, 3, 2, 0}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -339,20 +319,12 @@ TEST("test ONear Blueprint") { EXPECT_EQUAL(0u, a.exposeFields().size()); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(20).create()); - Blueprint::UP c2 = ap(MyLeafSpec(10).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c1.get(), children[0]); - EXPECT_EQUAL(c2.get(), children[1]); - EXPECT_EQUAL(c3.get(), children[2]); - EXPECT_EQUAL(c4.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(20).create(), + MyLeafSpec(10).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {0, 1, 2, 3}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -396,20 +368,12 @@ TEST("test Rank Blueprint") { EXPECT_EQUAL(true, got_global_filter(a.getChild(1))); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(20).create()); - Blueprint::UP c2 = ap(MyLeafSpec(10).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c1.get(), children[0]); - EXPECT_EQUAL(c2.get(), children[1]); - EXPECT_EQUAL(c3.get(), children[2]); - EXPECT_EQUAL(c4.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(20).create(), + MyLeafSpec(10).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {0, 1, 2, 3}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -469,20 +433,12 @@ TEST("test SourceBlender Blueprint") { EXPECT_EQUAL(0u, a->getState().numFields()); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(20).create()); - Blueprint::UP c2 = ap(MyLeafSpec(10).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c1.get(), children[0]); - EXPECT_EQUAL(c2.get(), children[1]); - EXPECT_EQUAL(c3.get(), children[2]); - EXPECT_EQUAL(c4.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(20).create(), + MyLeafSpec(10).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {0, 1, 2, 3}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); @@ -1080,20 +1036,12 @@ TEST("test WeakAnd Blueprint") { EXPECT_EQUAL(0u, a.exposeFields().size()); } { - std::vector<Blueprint *> children; - Blueprint::UP c1 = ap(MyLeafSpec(10).create()); - Blueprint::UP c2 = ap(MyLeafSpec(20).create()); - Blueprint::UP c3 = ap(MyLeafSpec(40).create()); - Blueprint::UP c4 = ap(MyLeafSpec(30).create()); - children.push_back(c1.get()); - children.push_back(c2.get()); - children.push_back(c3.get()); - children.push_back(c4.get()); - b.sort(children); - EXPECT_EQUAL(c1.get(), children[0]); - EXPECT_EQUAL(c2.get(), children[1]); - EXPECT_EQUAL(c3.get(), children[2]); - EXPECT_EQUAL(c4.get(), children[3]); + check_sort_order(b, + {MyLeafSpec(20).create(), + MyLeafSpec(10).create(), + MyLeafSpec(40).create(), + MyLeafSpec(30).create()}, + {0, 1, 2, 3}); } { EXPECT_EQUAL(true, b.inheritStrict(0)); diff --git a/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp b/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp index fe9f6424b9c..5741d210079 100644 --- a/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp +++ b/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp @@ -2,18 +2,17 @@ #include <vespa/searchlib/queryeval/simpleresult.h> #include <vespa/searchlib/queryeval/blueprint.h> +#include <vespa/searchlib/queryeval/intermediate_blueprints.h> #include <vespa/searchlib/queryeval/leaf_blueprints.h> +#include <vespa/searchlib/queryeval/isourceselector.h> #include <vespa/vespalib/util/trinary.h> #include <vespa/vespalib/util/require.h> #include <vespa/vespalib/gtest/gtest.h> #include <functional> -using search::queryeval::AlwaysTrueBlueprint; -using search::queryeval::Blueprint; -using search::queryeval::EmptyBlueprint; -using search::queryeval::SimpleBlueprint; -using search::queryeval::SimpleResult; -using search::queryeval::SearchIterator; +namespace search::fef { class MatchData; } + +using namespace search::queryeval; using vespalib::Trinary; using Constraint = Blueprint::FilterConstraint; @@ -27,37 +26,29 @@ concept FilterFactory = requires(const T &a, bool strict, Constraint upper_or_lo { a.createFilterSearch(strict, upper_or_lower) } -> std::same_as<std::unique_ptr<SearchIterator>>; }; -using factory_fun = std::function<std::unique_ptr<SearchIterator>(const std::vector<Blueprint*> &, bool, Constraint)>; - -// Combine children blueprints using a shared filter creation -// algorithm. Satisfies the FilterFactory concept. -struct Combine { - factory_fun fun; - std::vector<Blueprint*> list; - Combine(factory_fun fun_in) : fun(fun_in), list() {} - Combine &&add(std::unique_ptr<Blueprint> child) && { - list.push_back(child.release()); - return std::move(*this); - } - auto createFilterSearch(bool strict, Constraint upper_or_lower) const { - return fun(list, strict, upper_or_lower); - } - ~Combine() { - for (auto *ptr: list) { - delete ptr; - } - } +template <typename T> +concept FilterFactoryBuilder = requires(T a, std::unique_ptr<Blueprint> bp) { + { std::move(a).add(std::move(bp)) } -> std::same_as<T&&>; }; -// create a leaf blueprint that matches no documents -std::unique_ptr<Blueprint> empty() { - return std::make_unique<EmptyBlueprint>(); -} +// inherit Blueprint to capture the default filter factory +struct DefaultBlueprint : Blueprint { + void optimize(Blueprint* &) override { abort(); } + const State &getState() const override { abort(); } + void fetchPostings(const ExecuteInfo &) override { abort(); } + void freeze() override { abort(); } + SearchIteratorUP createSearch(search::fef::MatchData &, bool) const override { abort(); } +}; -// create a leaf blueprint that matches all documents -std::unique_ptr<Blueprint> full() { - return std::make_unique<AlwaysTrueBlueprint>(); -} +// need one of these to be able to create a SourceBlender +struct NullSelector : ISourceSelector { + NullSelector() : ISourceSelector(7) {} + void setSource(uint32_t, Source) override { abort(); } + uint32_t getDocIdLimit() const override { abort(); } + void compactLidSpace(uint32_t) override { abort(); } + std::unique_ptr<sourceselector::Iterator> createIterator() const override { abort(); } +}; +NullSelector null_selector; // make a simple result containing the given documents SimpleResult make_result(const std::vector<uint32_t> &docs) { @@ -82,11 +73,89 @@ SimpleResult make_empty_result() { return SimpleResult(); } +// create a leaf blueprint that matches no documents +std::unique_ptr<Blueprint> empty() { + return std::make_unique<EmptyBlueprint>(); +} + +// create a leaf blueprint that matches all documents +std::unique_ptr<Blueprint> full() { + return std::make_unique<AlwaysTrueBlueprint>(); +} + // create a leaf blueprint with the specified hits std::unique_ptr<Blueprint> leaf(const std::vector<uint32_t> &docs) { return std::make_unique<SimpleBlueprint>(make_result(docs)); } +// Describes blueprint children with a list of simple factories that +// can later be used to create them. +struct Children { + using Factory = std::function<Blueprint::UP()>; + std::vector<Factory> list; + Children() : list() {} + size_t size() const { return list.size(); } + Children &&leaf(const std::vector<uint32_t> &docs) && { + list.push_back([docs](){ return ::leaf(docs); }); + return std::move(*this); + } + Children &&full() && { + list.push_back([](){ return ::full(); }); + return std::move(*this); + } + Children &&empty() && { + list.push_back([](){ return ::empty(); }); + return std::move(*this); + } + template <FilterFactoryBuilder Builder> + Builder &&apply(Builder &&builder) const { + for (const Factory &make_child: list) { + std::move(builder).add(make_child()); + } + return std::move(builder); + } +}; + +// Combine children blueprints using a shared filter creation +// algorithm. Satisfies the FilterFactory concept. +struct Combine { + using factory_fun = std::function<std::unique_ptr<SearchIterator>(const Blueprint::Children &, bool, Constraint)>; + factory_fun fun; + Blueprint::Children list; + Combine(factory_fun fun_in) noexcept : fun(fun_in), list() {} + Combine &&add(std::unique_ptr<Blueprint> child) && { + list.push_back(std::move(child)); + return std::move(*this); + } + Combine &&add(const Children &children) && { + return children.apply(std::move(*this)); + } + auto createFilterSearch(bool strict, Constraint upper_or_lower) const { + return fun(list, strict, upper_or_lower); + } + ~Combine(); +}; +Combine::~Combine() = default; + +// Make a specific (intermediate) blueprint that you can add children +// to. Satisfies the FilterFactory concept. +template <FilterFactory T> +struct Make { + T blueprint; + template <typename ... Args> + Make(Args && ... args) : blueprint(std::forward<Args>(args)...) {} + Make &&add(std::unique_ptr<Blueprint> child) && { + blueprint.addChild(std::move(child)); + return std::move(*this); + } + Make &&add(const Children &children) && { + return children.apply(std::move(*this)); + } + auto createFilterSearch(bool strict, Constraint upper_or_lower) const { + return blueprint.createFilterSearch(strict, upper_or_lower); + } +}; + // what kind of results are we expecting from a filter search? struct Expect { Trinary matches_any; @@ -101,6 +170,8 @@ struct Expect { hits = make_empty_result(); } } + static Expect empty() { return Expect(Trinary::False); } + static Expect full() { return Expect(Trinary::True); } }; template <FilterFactory Blueprint> @@ -127,31 +198,67 @@ void verify(const Blueprint &blueprint, const Expect &upper_and_lower) { } TEST(FilterSearchTest, empty_leaf) { - verify(*empty(), Expect(Trinary::False)); + verify(*empty(), Expect::empty()); } TEST(FilterSearchTest, full_leaf) { - verify(*full(), Expect(Trinary::True)); + verify(*full(), Expect::full()); } TEST(FilterSearchTest, custom_leaf) { verify(*leaf({5,10,20}), Expect({5,10,20})); } +TEST(FilterSearchTest, default_blueprint) { + verify(DefaultBlueprint(), Expect::full(), Expect::empty()); +} + TEST(FilterSearchTest, simple_or) { - verify(Combine(Blueprint::create_or_filter) - .add(leaf({5, 10})) - .add(leaf({7})) - .add(leaf({3, 11})), - Expect({3, 5, 7, 10, 11})); + auto child_list = Children() + .leaf({5, 10}) + .leaf({7}) + .leaf({3, 11}); + auto expected = Expect({3, 5, 7, 10, 11}); + verify(Combine(Blueprint::create_or_filter).add(child_list), expected); + verify(Make<OrBlueprint>().add(child_list), expected); + verify(Combine(Blueprint::create_atmost_or_filter).add(child_list), expected, Expect::empty()); + verify(Make<WeakAndBlueprint>(child_list.size()).add(child_list), expected, Expect::empty()); + verify(Make<SourceBlenderBlueprint>(null_selector).add(child_list), expected, Expect::empty()); } TEST(FilterSearchTest, simple_and) { - verify(Combine(Blueprint::create_and_filter) - .add(leaf({1, 2, 3, 4, 5, 6})) - .add(leaf({2, 4, 6, 7})) - .add(leaf({1, 4, 6, 7, 10})), - Expect({4, 6})); + auto child_list = Children() + .leaf({1, 2, 3, 4, 5, 6}) + .leaf({2, 4, 6, 7}) + .leaf({1, 4, 6, 7, 10}); + auto expected = Expect({4, 6}); + verify(Combine(Blueprint::create_and_filter).add(child_list), expected); + verify(Make<AndBlueprint>().add(child_list), expected); + verify(Combine(Blueprint::create_atmost_and_filter).add(child_list), expected, Expect::empty()); + verify(Make<NearBlueprint>(3).add(child_list), expected, Expect::empty()); + verify(Make<ONearBlueprint>(3).add(child_list), expected, Expect::empty()); +} + +TEST(FilterSearchTest, simple_andnot) { + auto child_list = Children() + .leaf({1, 2, 3, 4, 5, 6}) + .leaf({2, 4, 6}) + .leaf({4, 6, 7}); + auto expected = Expect({1, 3, 5}); + verify(Combine(Blueprint::create_andnot_filter).add(child_list), expected); + verify(Make<AndNotBlueprint>().add(child_list), expected); +} + +TEST(FilterSearchTest, rank_filter) { + auto child_list1 = Children().leaf({1,2,3}).empty().full(); + auto child_list2 = Children().empty().leaf({1,2,3}).full(); + auto child_list3 = Children().full().leaf({1,2,3}).empty(); + verify(Combine(Blueprint::create_first_child_filter).add(child_list1), Expect({1,2,3})); + verify(Combine(Blueprint::create_first_child_filter).add(child_list2), Expect::empty()); + verify(Combine(Blueprint::create_first_child_filter).add(child_list3), Expect::full()); + verify(Make<RankBlueprint>().add(child_list1), Expect({1,2,3})); + verify(Make<RankBlueprint>().add(child_list2), Expect::empty()); + verify(Make<RankBlueprint>().add(child_list3), Expect::full()); } GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp index ff83dd92f3b..29a9fd96118 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp @@ -8,6 +8,7 @@ #include "field_spec.hpp" #include "andsearch.h" #include "orsearch.h" +#include "andnotsearch.h" #include "matching_elements_search.h" #include <vespa/searchlib/fef/termfieldmatchdataarray.h> #include <vespa/vespalib/objects/visit.hpp> @@ -159,9 +160,19 @@ Blueprint::create_matching_elements_search(const MatchingElementsFields &fields) namespace { +Blueprint::FilterConstraint invert(Blueprint::FilterConstraint constraint) { + if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { + return Blueprint::FilterConstraint::LOWER_BOUND; + } + if (constraint == Blueprint::FilterConstraint::LOWER_BOUND) { + return Blueprint::FilterConstraint::UPPER_BOUND; + } + abort(); +} + template <typename Op> std::unique_ptr<SearchIterator> -create_op_filter(const std::vector<Blueprint *>& children, bool strict, Blueprint::FilterConstraint constraint) +create_op_filter(const Blueprint::Children &children, bool strict, Blueprint::FilterConstraint constraint) { MultiSearch::Children sub_searches; sub_searches.reserve(children.size()); @@ -178,17 +189,58 @@ create_op_filter(const std::vector<Blueprint *>& children, bool strict, Blueprin } std::unique_ptr<SearchIterator> -Blueprint::create_and_filter(const std::vector<Blueprint *>& children, bool strict, Blueprint::FilterConstraint constraint) +Blueprint::create_and_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) { return create_op_filter<AndSearch>(children, strict, constraint); } std::unique_ptr<SearchIterator> -Blueprint::create_or_filter(const std::vector<Blueprint *>& children, bool strict, Blueprint::FilterConstraint constraint) +Blueprint::create_or_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) { return create_op_filter<OrSearch>(children, strict, constraint); } +std::unique_ptr<SearchIterator> +Blueprint::create_atmost_and_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) +{ + if (constraint == FilterConstraint::UPPER_BOUND) { + return create_and_filter(children, strict, constraint); + } else { + return std::make_unique<EmptySearch>(); + } +} + +std::unique_ptr<SearchIterator> +Blueprint::create_atmost_or_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) +{ + if (constraint == FilterConstraint::UPPER_BOUND) { + return create_or_filter(children, strict, constraint); + } else { + return std::make_unique<EmptySearch>(); + } +} + +std::unique_ptr<SearchIterator> +Blueprint::create_andnot_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) +{ + MultiSearch::Children sub_searches; + sub_searches.reserve(children.size()); + for (size_t i = 0; i < children.size(); ++i) { + auto search = (i == 0) + ? children[i]->createFilterSearch(strict, constraint) + : children[i]->createFilterSearch(false, invert(constraint)); + sub_searches.push_back(std::move(search)); + } + return AndNotSearch::create(std::move(sub_searches), strict); +} + +std::unique_ptr<SearchIterator> +Blueprint::create_first_child_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint) +{ + assert(children.size() > 0); + return children[0]->createFilterSearch(strict, constraint); +} + vespalib::string Blueprint::asString() const { @@ -263,19 +315,13 @@ StateCache::notifyChange() { //----------------------------------------------------------------------------- -IntermediateBlueprint::~IntermediateBlueprint() -{ - while (!_children.empty()) { - delete _children.back(); - _children.pop_back(); - } -} +IntermediateBlueprint::~IntermediateBlueprint() = default; void IntermediateBlueprint::setDocIdLimit(uint32_t limit) { Blueprint::setDocIdLimit(limit); - for (Blueprint * child : _children) { + for (Blueprint::UP &child : _children) { child->setDocIdLimit(limit); } } @@ -285,7 +331,7 @@ IntermediateBlueprint::calculateEstimate() const { std::vector<HitEstimate> estimates; estimates.reserve(_children.size()); - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { estimates.push_back(child->getState().estimate()); } return combine(estimates); @@ -295,7 +341,7 @@ uint32_t IntermediateBlueprint::calculate_cost_tier() const { uint32_t cost_tier = State::COST_TIER_MAX; - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { cost_tier = std::min(cost_tier, child->getState().cost_tier()); } return cost_tier; @@ -305,7 +351,7 @@ uint32_t IntermediateBlueprint::calculate_tree_size() const { uint32_t nodes = 1; - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { nodes += child->getState().tree_size(); } return nodes; @@ -317,7 +363,7 @@ IntermediateBlueprint::infer_allow_termwise_eval() const if (!supports_termwise_children()) { return false; } - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { if (!child->getState().allow_termwise_eval()) { return false; } @@ -328,7 +374,7 @@ IntermediateBlueprint::infer_allow_termwise_eval() const bool IntermediateBlueprint::infer_want_global_filter() const { - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { if (child->getState().want_global_filter()) { return true; } @@ -371,7 +417,7 @@ IntermediateBlueprint::mixChildrenFields() const Map fieldMap; FieldSpecBaseList fieldList; - for (const Blueprint * child : _children) { + for (const Blueprint::UP &child : _children) { const State &childState = child->getState(); if (!childState.isTermLike()) { return fieldList; // empty: non-term-like child @@ -431,8 +477,10 @@ IntermediateBlueprint::optimize(Blueprint* &self) { assert(self == this); if (should_optimize_children()) { - for (auto & child : _children) { - child->optimize(child); + for (auto &child : _children) { + auto *child_ptr = child.release(); + child_ptr->optimize(child_ptr); + child.reset(child_ptr); } } optimize_self(); @@ -467,8 +515,8 @@ IntermediateBlueprint::IntermediateBlueprint() = default; IntermediateBlueprint & IntermediateBlueprint::addChild(Blueprint::UP child) { - _children.push_back(child.get()); - child.release()->setParent(this); + child->setParent(this); + _children.push_back(std::move(child)); notifyChange(); return *this; } @@ -477,9 +525,9 @@ Blueprint::UP IntermediateBlueprint::removeChild(size_t n) { assert(n < _children.size()); - Blueprint::UP ret(_children[n]); + Blueprint::UP ret = std::move(_children[n]); _children.erase(_children.begin() + n); - ret->setParent(0); + ret->setParent(nullptr); notifyChange(); return ret; } @@ -488,8 +536,8 @@ IntermediateBlueprint & IntermediateBlueprint::insertChild(size_t n, Blueprint::UP child) { assert(n <= _children.size()); - _children.insert(_children.begin() + n, child.get()); - child.release()->setParent(this); + child->setParent(this); + _children.insert(_children.begin() + n, std::move(child)); notifyChange(); return *this; } @@ -515,7 +563,7 @@ IntermediateBlueprint::fetchPostings(const ExecuteInfo &execInfo) void IntermediateBlueprint::freeze() { - for (Blueprint * child : _children) { + for (Blueprint::UP &child: _children) { child->freeze(); } freeze_self(); diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h index 6dbd3cb9a5c..199cf45792d 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h @@ -40,8 +40,9 @@ class MatchingElementsSearch; class Blueprint { public: - typedef std::unique_ptr<Blueprint> UP; - typedef std::unique_ptr<SearchIterator> SearchIteratorUP; + using UP = std::unique_ptr<Blueprint>; + using Children = std::vector<Blueprint::UP>; + using SearchIteratorUP = std::unique_ptr<SearchIterator>; struct HitEstimate { uint32_t estHits; @@ -127,7 +128,7 @@ public: // utility to get the greater estimate to sort first, higher tiers last struct TieredGreaterEstimate { - bool operator () (Blueprint * const &a, Blueprint * const &b) const { + bool operator () (const auto &a, const auto &b) const { const auto &lhs = a->getState(); const auto &rhs = b->getState(); if (lhs.cost_tier() != rhs.cost_tier()) { @@ -139,7 +140,7 @@ public: // utility to get the lesser estimate to sort first, higher tiers last struct TieredLessEstimate { - bool operator () (Blueprint * const &a, const Blueprint * const &b) const { + bool operator () (const auto &a, const auto &b) const { const auto &lhs = a->getState(); const auto &rhs = b->getState(); if (lhs.cost_tier() != rhs.cost_tier()) { @@ -225,8 +226,12 @@ public: virtual SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const = 0; virtual SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const; - static std::unique_ptr<SearchIterator> create_and_filter(const std::vector<Blueprint *>& children, bool strict, FilterConstraint constraint); - static std::unique_ptr<SearchIterator> create_or_filter(const std::vector<Blueprint *>& children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_and_filter(const Children &children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_or_filter(const Children &children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_atmost_and_filter(const Children &children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_atmost_or_filter(const Children &children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_andnot_filter(const Children &children, bool strict, FilterConstraint constraint); + static SearchIteratorUP create_first_child_filter(const Children &children, bool strict, FilterConstraint constraint); // for debug dumping vespalib::string asString() const; @@ -278,8 +283,6 @@ public: class IntermediateBlueprint : public blueprint::StateCache { -public: - typedef std::vector<Blueprint*> Children; private: Children _children; HitEstimate calculateEstimate() const; @@ -325,7 +328,7 @@ public: virtual HitEstimate combine(const std::vector<HitEstimate> &data) const = 0; virtual FieldSpecBaseList exposeFields() const = 0; - virtual void sort(std::vector<Blueprint*> &children) const = 0; + virtual void sort(Children &children) const = 0; virtual bool inheritStrict(size_t i) const = 0; virtual SearchIteratorUP createIntermediateSearch(MultiSearch::Children subSearches, diff --git a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp index 1e2b8109778..61b717b1104 100644 --- a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp @@ -16,13 +16,7 @@ DotProductBlueprint::DotProductBlueprint(const FieldSpec &field) { } -DotProductBlueprint::~DotProductBlueprint() -{ - while (!_terms.empty()) { - delete _terms.back(); - _terms.pop_back(); - } -} +DotProductBlueprint::~DotProductBlueprint() = default; FieldSpec DotProductBlueprint::getNextChildField(const FieldSpec &outer) @@ -43,8 +37,7 @@ DotProductBlueprint::addTerm(Blueprint::UP term, int32_t weight) setEstimate(_estimate); } _weights.push_back(weight); - _terms.push_back(term.get()); - term.release(); + _terms.push_back(std::move(term)); } SearchIterator::UP diff --git a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h index d1992fc67c5..4ba59ba755f 100644 --- a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h @@ -11,10 +11,10 @@ namespace search::queryeval { class DotProductBlueprint : public ComplexLeafBlueprint { - HitEstimate _estimate; - fef::MatchDataLayout _layout; - std::vector<int32_t> _weights; - std::vector<Blueprint*> _terms; + HitEstimate _estimate; + fef::MatchDataLayout _layout; + std::vector<int32_t> _weights; + std::vector<Blueprint::UP> _terms; public: explicit DotProductBlueprint(const FieldSpec &field); diff --git a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp index d93134447d0..c2f4c53224d 100644 --- a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp @@ -79,13 +79,7 @@ EquivBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &outputs, bo SearchIterator::UP EquivBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - MultiSearch::Children children; - children.reserve(_terms.size()); - for (size_t i = 0; i < _terms.size(); ++i) { - children.push_back(_terms[i]->createFilterSearch(strict, constraint)); - } - UnpackInfo unpack_info; - return OrSearch::create(std::move(children), strict, unpack_info); + return create_or_filter(_terms, strict, constraint); } void diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp index 79d78c3faab..9a29c4c0caf 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp @@ -83,16 +83,6 @@ need_normal_features_for_children(const IntermediateBlueprint &blueprint, fef::M } } -/** utility for operators that degrade to AND when creating filter */ -SearchIterator::UP createAndFilter(const IntermediateBlueprint &self, - const std::vector<Blueprint *>& children, - bool strict, Blueprint::FilterConstraint constraint) -{ - auto search = Blueprint::create_and_filter(children, strict, constraint); - static_cast<AndSearch &>(*search).estimate(self.getState().estimate().estHits); - return search; -} - } // namespace search::queryeval::<unnamed> //----------------------------------------------------------------------------- @@ -146,7 +136,7 @@ AndNotBlueprint::get_replacement() } void -AndNotBlueprint::sort(std::vector<Blueprint*> &children) const +AndNotBlueprint::sort(Children &children) const { if (children.size() > 2) { std::sort(children.begin() + 1, children.end(), TieredGreaterEstimate()); @@ -180,31 +170,10 @@ AndNotBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, return AndNotSearch::create(std::move(sub_searches), strict); } -namespace { -Blueprint::FilterConstraint invert(Blueprint::FilterConstraint constraint) { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - return Blueprint::FilterConstraint::LOWER_BOUND; - } - if (constraint == Blueprint::FilterConstraint::LOWER_BOUND) { - return Blueprint::FilterConstraint::UPPER_BOUND; - } - abort(); -} -} // namespace <unnamed> - SearchIterator::UP AndNotBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - MultiSearch::Children sub_searches; - sub_searches.reserve(childCnt()); - for (size_t i = 0; i < childCnt(); ++i) { - bool child_strict = strict && inheritStrict(i); - auto search = (i == 0) - ? getChild(i).createFilterSearch(child_strict, constraint) - : getChild(i).createFilterSearch(child_strict, invert(constraint)); - sub_searches.push_back(std::move(search)); - } - return AndNotSearch::create(std::move(sub_searches), strict); + return create_andnot_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -248,7 +217,7 @@ AndBlueprint::get_replacement() } void -AndBlueprint::sort(std::vector<Blueprint*> &children) const +AndBlueprint::sort(Children &children) const { std::sort(children.begin(), children.end(), TieredLessEstimate()); } @@ -286,7 +255,7 @@ AndBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP AndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - return createAndFilter(*this, get_children(), strict, constraint); + return create_and_filter(get_children(), strict, constraint); } double @@ -339,7 +308,7 @@ OrBlueprint::get_replacement() } void -OrBlueprint::sort(std::vector<Blueprint*> &children) const +OrBlueprint::sort(Children &children) const { std::sort(children.begin(), children.end(), TieredGreaterEstimate()); } @@ -372,15 +341,7 @@ OrBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP OrBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - MultiSearch::Children sub_searches; - sub_searches.reserve(childCnt()); - for (size_t i = 0; i < childCnt(); ++i) { - bool child_strict = strict && inheritStrict(i); - auto search = getChild(i).createFilterSearch(child_strict, constraint); - sub_searches.push_back(std::move(search)); - } - UnpackInfo unpack_info; - return OrSearch::create(std::move(sub_searches), strict, unpack_info); + return create_or_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -404,7 +365,7 @@ WeakAndBlueprint::exposeFields() const } void -WeakAndBlueprint::sort(std::vector<Blueprint*> &) const +WeakAndBlueprint::sort(Children &) const { // order needs to stay the same as _weights } @@ -440,11 +401,7 @@ WeakAndBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP WeakAndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - return create_or_filter(get_children(), strict, constraint); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_or_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -462,7 +419,7 @@ NearBlueprint::exposeFields() const } void -NearBlueprint::sort(std::vector<Blueprint*> &children) const +NearBlueprint::sort(Children &children) const { std::sort(children.begin(), children.end(), TieredLessEstimate()); } @@ -497,11 +454,7 @@ NearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP NearBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - return createAndFilter(*this, get_children(), strict, constraint); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_and_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -519,7 +472,7 @@ ONearBlueprint::exposeFields() const } void -ONearBlueprint::sort(std::vector<Blueprint*> &children) const +ONearBlueprint::sort(Children &children) const { // ordered near cannot sort children here (void)children; @@ -557,11 +510,7 @@ ONearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP ONearBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - return createAndFilter(*this, get_children(), strict, constraint); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_and_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -602,7 +551,7 @@ RankBlueprint::get_replacement() } void -RankBlueprint::sort(std::vector<Blueprint*> &children) const +RankBlueprint::sort(Children &children) const { (void)children; } @@ -642,8 +591,7 @@ RankBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches, SearchIterator::UP RankBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - assert(childCnt() > 0); - return getChild(0).createFilterSearch(strict, constraint); + return create_first_child_filter(get_children(), strict, constraint); } //----------------------------------------------------------------------------- @@ -666,7 +614,7 @@ SourceBlenderBlueprint::exposeFields() const } void -SourceBlenderBlueprint::sort(std::vector<Blueprint*> &) const +SourceBlenderBlueprint::sort(Children &) const { } @@ -716,19 +664,7 @@ SourceBlenderBlueprint::createIntermediateSearch(MultiSearch::Children sub_searc SearchIterator::UP SourceBlenderBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == FilterConstraint::UPPER_BOUND) { - MultiSearch::Children sub_searches; - sub_searches.reserve(childCnt()); - for (size_t i = 0; i < childCnt(); ++i) { - bool child_strict = strict && inheritStrict(i); - auto search = getChild(i).createFilterSearch(child_strict, constraint); - sub_searches.push_back(std::move(search)); - } - UnpackInfo unpack_info; - return OrSearch::create(std::move(sub_searches), strict, unpack_info); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_or_filter(get_children(), strict, constraint); } bool diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h index c8bd26fe4a7..f4ae2e21b41 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h @@ -20,7 +20,7 @@ public: void optimize_self() override; bool isAndNot() const override { return true; } Blueprint::UP get_replacement() override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; SearchIterator::UP createIntermediateSearch(MultiSearch::Children subSearches, @@ -43,7 +43,7 @@ public: void optimize_self() override; bool isAnd() const override { return true; } Blueprint::UP get_replacement() override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; SearchIterator::UP createIntermediateSearch(MultiSearch::Children subSearches, @@ -67,7 +67,7 @@ public: void optimize_self() override; bool isOr() const override { return true; } Blueprint::UP get_replacement() override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; SearchIterator::UP createIntermediateSearch(MultiSearch::Children subSearches, @@ -87,7 +87,7 @@ private: public: HitEstimate combine(const std::vector<HitEstimate> &data) const override; FieldSpecBaseList exposeFields() const override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; bool always_needs_unpack() const override; SearchIterator::UP @@ -116,7 +116,7 @@ public: HitEstimate combine(const std::vector<HitEstimate> &data) const override; FieldSpecBaseList exposeFields() const override; bool should_optimize_children() const override { return false; } - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override; SearchIterator::UP @@ -138,7 +138,7 @@ public: HitEstimate combine(const std::vector<HitEstimate> &data) const override; FieldSpecBaseList exposeFields() const override; bool should_optimize_children() const override { return false; } - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override; SearchIterator::UP @@ -158,7 +158,7 @@ public: FieldSpecBaseList exposeFields() const override; void optimize_self() override; Blueprint::UP get_replacement() override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; bool isRank() const override { return true; } SearchIterator::UP @@ -179,7 +179,7 @@ public: SourceBlenderBlueprint(const ISourceSelector &selector); HitEstimate combine(const std::vector<HitEstimate> &data) const override; FieldSpecBaseList exposeFields() const override; - void sort(std::vector<Blueprint*> &children) const override; + void sort(Children &children) const override; bool inheritStrict(size_t i) const override; /** * Will return the index matching the given sourceId. diff --git a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp index e2a22c16631..aeaa0f98c2f 100644 --- a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp @@ -93,19 +93,7 @@ SameElementBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArra SearchIterator::UP SameElementBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - MultiSearch::Children sub_searches; - sub_searches.reserve(_terms.size()); - for (size_t i = 0; i < _terms.size(); ++i) { - auto search = _terms[i]->createFilterSearch(strict && (i == 0), constraint); - sub_searches.push_back(std::move(search)); - } - UnpackInfo unpack_info; - auto search = AndSearch::create(std::move(sub_searches), strict, unpack_info); - return search; - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_and_filter(_terms, strict, constraint); } void diff --git a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp index 2ef7a2cf0a0..9a8e03c0651 100644 --- a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp @@ -23,13 +23,7 @@ SimplePhraseBlueprint::SimplePhraseBlueprint(const FieldSpec &field, bool expens } } -SimplePhraseBlueprint::~SimplePhraseBlueprint() -{ - while (!_terms.empty()) { - delete _terms.back(); - _terms.pop_back(); - } -} +SimplePhraseBlueprint::~SimplePhraseBlueprint() = default; FieldSpec SimplePhraseBlueprint::getNextChildField(const FieldSpec &outer) @@ -51,7 +45,7 @@ SimplePhraseBlueprint::addTerm(Blueprint::UP term) _estimate = childEst; } setEstimate(_estimate); - _terms.push_back(term.release()); + _terms.push_back(std::move(term)); } SearchIterator::UP @@ -87,18 +81,7 @@ SimplePhraseBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmd SearchIterator::UP SimplePhraseBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == FilterConstraint::UPPER_BOUND) { - MultiSearch::Children children; - children.reserve(_terms.size()); - for (size_t i = 0; i < _terms.size(); ++i) { - bool child_strict = strict && (i == 0); - children.push_back(_terms[i]->createFilterSearch(child_strict, constraint)); - } - UnpackInfo unpack_info; - return AndSearch::create(std::move(children), strict, unpack_info); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_and_filter(_terms, strict, constraint); } void diff --git a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h index 0cfb2357321..c4faf3951f6 100644 --- a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h @@ -12,10 +12,10 @@ namespace search::queryeval { class SimplePhraseBlueprint : public ComplexLeafBlueprint { private: - FieldSpec _field; - HitEstimate _estimate; - fef::MatchDataLayout _layout; - std::vector<Blueprint*> _terms; + FieldSpec _field; + HitEstimate _estimate; + fef::MatchDataLayout _layout; + std::vector<Blueprint::UP> _terms; public: SimplePhraseBlueprint(const FieldSpec &field, bool expensive); diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp index 961c8785b40..fe212666ec9 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp @@ -47,13 +47,7 @@ ParallelWeakAndBlueprint::ParallelWeakAndBlueprint(const FieldSpec &field, { } -ParallelWeakAndBlueprint::~ParallelWeakAndBlueprint() -{ - while (!_terms.empty()) { - delete _terms.back(); - _terms.pop_back(); - } -} +ParallelWeakAndBlueprint::~ParallelWeakAndBlueprint() = default; FieldSpec ParallelWeakAndBlueprint::getNextChildField(const FieldSpec &outer) @@ -74,8 +68,7 @@ ParallelWeakAndBlueprint::addTerm(Blueprint::UP term, int32_t weight) setEstimate(_estimate); } _weights.push_back(weight); - _terms.push_back(term.get()); - term.release(); + _terms.push_back(std::move(term)); set_tree_size(_terms.size() + 1); } @@ -107,11 +100,7 @@ ParallelWeakAndBlueprint::createLeafSearch(const search::fef::TermFieldMatchData std::unique_ptr<SearchIterator> ParallelWeakAndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const { - if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) { - return create_or_filter(_terms, strict, constraint); - } else { - return std::make_unique<EmptySearch>(); - } + return create_atmost_or_filter(_terms, strict, constraint); } void diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h index cf0b6c1b254..39d2b5a03f0 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h @@ -29,7 +29,7 @@ private: HitEstimate _estimate; fef::MatchDataLayout _layout; std::vector<int32_t> _weights; - std::vector<Blueprint*> _terms; + std::vector<Blueprint::UP> _terms; ParallelWeakAndBlueprint(const ParallelWeakAndBlueprint &); ParallelWeakAndBlueprint &operator=(const ParallelWeakAndBlueprint &); diff --git a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp index 4862d9a2375..f855b72812a 100644 --- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp @@ -15,17 +15,17 @@ class WeightedSetTermMatchingElementsSearch : public MatchingElementsSearch fef::TermFieldMatchData _tfmd; fef::TermFieldMatchDataArray _tfmda; vespalib::string _field_name; - const std::vector<Blueprint*>& _terms; + const std::vector<Blueprint::UP> &_terms; std::unique_ptr<WeightedSetTermSearch> _search; public: - WeightedSetTermMatchingElementsSearch(const WeightedSetTermBlueprint& bp, const vespalib::string& field_name, const std::vector<Blueprint*>& terms); + WeightedSetTermMatchingElementsSearch(const WeightedSetTermBlueprint& bp, const vespalib::string& field_name, const std::vector<Blueprint::UP> &terms); ~WeightedSetTermMatchingElementsSearch() override; void find_matching_elements(uint32_t docid, MatchingElements& result) override; void initRange(uint32_t begin_id, uint32_t end_id) override; }; -WeightedSetTermMatchingElementsSearch::WeightedSetTermMatchingElementsSearch(const WeightedSetTermBlueprint& bp, const vespalib::string& field_name, const std::vector<Blueprint*>& terms) +WeightedSetTermMatchingElementsSearch::WeightedSetTermMatchingElementsSearch(const WeightedSetTermBlueprint& bp, const vespalib::string& field_name, const std::vector<Blueprint::UP> &terms) : _tfmd(), _tfmda(), _field_name(field_name), @@ -71,13 +71,7 @@ WeightedSetTermBlueprint::WeightedSetTermBlueprint(const FieldSpec &field) set_allow_termwise_eval(true); } -WeightedSetTermBlueprint::~WeightedSetTermBlueprint() -{ - while (!_terms.empty()) { - delete _terms.back(); - _terms.pop_back(); - } -} +WeightedSetTermBlueprint::~WeightedSetTermBlueprint() = default; void WeightedSetTermBlueprint::addTerm(Blueprint::UP term, int32_t weight) @@ -92,8 +86,7 @@ WeightedSetTermBlueprint::addTerm(Blueprint::UP term, int32_t weight) setEstimate(_estimate); } _weights.push_back(weight); - _terms.push_back(term.get()); - term.release(); + _terms.push_back(std::move(term)); } diff --git a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h index a840310d3d9..2a3db3ec52d 100644 --- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h @@ -12,11 +12,11 @@ namespace search::queryeval { class WeightedSetTermBlueprint : public ComplexLeafBlueprint { - HitEstimate _estimate; - fef::MatchDataLayout _layout; - FieldSpec _children_field; - std::vector<int32_t> _weights; - std::vector<Blueprint*> _terms; + HitEstimate _estimate; + fef::MatchDataLayout _layout; + FieldSpec _children_field; + std::vector<int32_t> _weights; + std::vector<Blueprint::UP> _terms; public: WeightedSetTermBlueprint(const FieldSpec &field); @@ -37,7 +37,7 @@ public: std::unique_ptr<MatchingElementsSearch> create_matching_elements_search(const MatchingElementsFields &fields) const override; void visitMembers(vespalib::ObjectVisitor &visitor) const override; const vespalib::string &field_name() const { return _children_field.getName(); } - const std::vector<Blueprint*>& get_terms() const { return _terms; } + const std::vector<Blueprint::UP> &get_terms() const { return _terms; } private: void fetchPostings(const ExecuteInfo &execInfo) override; diff --git a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.cpp b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.cpp index 0eebfb9f690..375f570160a 100644 --- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.cpp @@ -50,7 +50,7 @@ private: void seek_child(ref_t child, uint32_t docId) { _termPos[child] = _children.seek(child, docId); } - void get_matching_elements_child(ref_t child, uint32_t docId, const std::vector<Blueprint *> &child_blueprints, std::vector<uint32_t> &dst) { + void get_matching_elements_child(ref_t child, uint32_t docId, const std::vector<Blueprint::UP> &child_blueprints, std::vector<uint32_t> &dst) { auto *sc = child_blueprints[child]->get_attribute_search_context(); if (sc != nullptr) { int32_t weight(0); @@ -151,7 +151,7 @@ public: void and_hits_into(BitVector &result, uint32_t begin_id) override { result.andWith(*get_hits(begin_id)); } - void find_matching_elements(uint32_t docId, const std::vector<Blueprint *>& child_blueprints, std::vector<uint32_t> &dst) override { + void find_matching_elements(uint32_t docId, const std::vector<Blueprint::UP> &child_blueprints, std::vector<uint32_t> &dst) override { pop_matching_children(docId); for (ref_t *ptr = _data_stash; ptr < _data_end; ++ptr) { get_matching_elements_child(*ptr, docId, child_blueprints, dst); diff --git a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.h b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.h index 3aaf3477bbd..e3e12c27f28 100644 --- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.h +++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.h @@ -44,7 +44,7 @@ public: // used during docsum fetching to identify matching elements // initRange must be called before use. // doSeek/doUnpack must not be called. - virtual void find_matching_elements(uint32_t docid, const std::vector<Blueprint *>& child_blueprints, std::vector<uint32_t> &dst) = 0; + virtual void find_matching_elements(uint32_t docid, const std::vector<std::unique_ptr<Blueprint>> &child_blueprints, std::vector<uint32_t> &dst) = 0; }; } // namespace search::queryeval |