summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2022-10-25 10:53:41 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2022-10-25 14:05:13 +0000
commit1c90a1aff5d166d1223edd00e82f9f7f3a64df48 (patch)
tree1fe8e7650ee3003d6f08b9fe59e8aa0c4eb2e7a1 /searchlib
parent70026cc89de5a1586f7b70e261d0f09c437a2263 (diff)
use common algorithms for filter creation
add more testing keep children blueprints in unique pointers
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp2
-rw-r--r--searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp172
-rw-r--r--searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp199
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.cpp100
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.h21
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp11
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp96
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h16
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp14
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp23
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp17
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h2
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp17
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h12
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_search.h2
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