aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2024-03-14 12:40:34 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2024-03-20 12:59:59 +0000
commit97da6db442eb0385571f834c75a8d65bd239c620 (patch)
treeb78347b8987ad09d7340b42ffdbe445438daf020 /searchlib
parent7938460dd3b3d72ec1900febe29c1a94db964648 (diff)
tag blueprints with strictness
The strict-aware sort function is responsible for propagating and tagging strictness throughout the blueprint tree. Use pre-tagged strictness in fetchPostings, createSearch and createFilterSearch.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/apps/tests/memoryindexstress_test.cpp12
-rw-r--r--searchlib/src/tests/attribute/benchmark/attributesearcher.h6
-rw-r--r--searchlib/src/tests/attribute/bitvector/bitvector_test.cpp2
-rw-r--r--searchlib/src/tests/attribute/direct_multi_term_blueprint/direct_multi_term_blueprint_test.cpp6
-rw-r--r--searchlib/src/tests/attribute/enumeratedsave/enumeratedsave_test.cpp2
-rw-r--r--searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp22
-rw-r--r--searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp12
-rw-r--r--searchlib/src/tests/attribute/searchable/attribute_searchable_adapter_test.cpp5
-rw-r--r--searchlib/src/tests/attribute/searchable/attribute_weighted_set_blueprint_test.cpp10
-rw-r--r--searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp16
-rw-r--r--searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp22
-rw-r--r--searchlib/src/tests/diskindex/diskindex/diskindex_test.cpp30
-rw-r--r--searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp12
-rw-r--r--searchlib/src/tests/nearsearch/nearsearch_test.cpp7
-rw-r--r--searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp54
-rw-r--r--searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp219
-rw-r--r--searchlib/src/tests/queryeval/blueprint/leaf_blueprints_test.cpp15
-rw-r--r--searchlib/src/tests/queryeval/blueprint/mysearch.h8
-rw-r--r--searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp5
-rw-r--r--searchlib/src/tests/queryeval/equiv/equiv_test.cpp5
-rw-r--r--searchlib/src/tests/queryeval/fake_searchable/fake_searchable_test.cpp35
-rw-r--r--searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp261
-rw-r--r--searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp13
-rw-r--r--searchlib/src/tests/queryeval/parallel_weak_and/parallel_weak_and_test.cpp12
-rw-r--r--searchlib/src/tests/queryeval/predicate/predicate_blueprint_test.cpp25
-rw-r--r--searchlib/src/tests/queryeval/queryeval_test.cpp56
-rw-r--r--searchlib/src/tests/queryeval/same_element/same_element_test.cpp15
-rw-r--r--searchlib/src/tests/queryeval/simple_phrase/simple_phrase_test.cpp14
-rw-r--r--searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp5
-rw-r--r--searchlib/src/tests/queryeval/termwise_eval/termwise_eval_test.cpp55
-rw-r--r--searchlib/src/tests/queryeval/weighted_set_term/weighted_set_term_test.cpp23
-rw-r--r--searchlib/src/vespa/searchcommon/attribute/i_search_context.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp57
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.h5
-rw-r--r--searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.h8
-rw-r--r--searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.hpp8
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/imported_search_context.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/ipostinglistsearchcontext.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h6
-rw-r--r--searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp4
-rw-r--r--searchlib/src/vespa/searchlib/attribute/search_context.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/attribute/search_context.h2
-rw-r--r--searchlib/src/vespa/searchlib/attribute/singleboolattribute.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/diskindex/disktermblueprint.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/diskindex/disktermblueprint.h4
-rw-r--r--searchlib/src/vespa/searchlib/memoryindex/field_index.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.cpp93
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.h73
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp17
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h5
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp21
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.h5
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/executeinfo.cpp9
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/executeinfo.h32
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/global_filter.cpp3
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp137
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h44
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h18
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.h8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.h7
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp27
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h5
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.cpp21
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_blueprint.h5
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp21
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h5
75 files changed, 1006 insertions, 756 deletions
diff --git a/searchlib/src/apps/tests/memoryindexstress_test.cpp b/searchlib/src/apps/tests/memoryindexstress_test.cpp
index 1cf7c4f95e5..763ba860fe6 100644
--- a/searchlib/src/apps/tests/memoryindexstress_test.cpp
+++ b/searchlib/src/apps/tests/memoryindexstress_test.cpp
@@ -63,7 +63,7 @@ const vespalib::string bar("bar");
const vespalib::string doc_type_name = "test";
const vespalib::string header_name = doc_type_name + ".header";
const vespalib::string body_name = doc_type_name + ".body";
-
+uint32_t docid_limit = 100; // needed for relative estimates
Schema
makeSchema()
@@ -332,13 +332,14 @@ Fixture::readWork(uint32_t cnt)
LOG(error, "Did not get blueprint");
break;
}
+ result->basic_plan(true, docid_limit);
if (result->getState().estimate().empty) {
++emptyCount;
} else {
++nonEmptyCount;
}
- result->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = result->createSearch(*match_data, true);
+ result->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = result->createSearch(*match_data);
if (!EXPECT_TRUE(search)) {
LOG(error, "Did not get search iterator");
break;
@@ -429,11 +430,12 @@ verifyResult(const FakeResult &expect,
if (!EXPECT_TRUE(result.get() != 0)) {
return false;
}
+ result->basic_plan(true, docid_limit);
EXPECT_EQUAL(expect.inspect().size(), result->getState().estimate().estHits);
EXPECT_EQUAL(expect.inspect().empty(), result->getState().estimate().empty);
- result->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = result->createSearch(*match_data, true);
+ result->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = result->createSearch(*match_data);
if (!EXPECT_TRUE(search.get() != 0)) {
return false;
}
diff --git a/searchlib/src/tests/attribute/benchmark/attributesearcher.h b/searchlib/src/tests/attribute/benchmark/attributesearcher.h
index a383b22e22f..6b8ccc5de59 100644
--- a/searchlib/src/tests/attribute/benchmark/attributesearcher.h
+++ b/searchlib/src/tests/attribute/benchmark/attributesearcher.h
@@ -140,7 +140,7 @@ AttributeFindSearcher<T>::doRun()
_attrPtr->getSearch(vespalib::stringref(&_query[0], _query.size()),
attribute::SearchContextParams());
- searchContext->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ searchContext->fetchPostings(queryeval::ExecuteInfo::FULL, true);
std::unique_ptr<queryeval::SearchIterator> iterator = searchContext->createIterator(nullptr, true);
std::unique_ptr<ResultSet> results = performSearch(*iterator, _attrPtr->getNumDocs());
@@ -218,7 +218,7 @@ AttributeRangeSearcher::doRun()
_attrPtr->getSearch(vespalib::stringref(&_query[0], _query.size()),
attribute::SearchContextParams());
- searchContext->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ searchContext->fetchPostings(queryeval::ExecuteInfo::FULL, true);
std::unique_ptr<queryeval::SearchIterator> iterator = searchContext->createIterator(nullptr, true);
std::unique_ptr<ResultSet> results = performSearch(*iterator, _attrPtr->getNumDocs());
@@ -257,7 +257,7 @@ AttributePrefixSearcher::doRun()
_attrPtr->getSearch(vespalib::stringref(&_query[0], _query.size()),
attribute::SearchContextParams());
- searchContext->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ searchContext->fetchPostings(queryeval::ExecuteInfo::FULL, true);
std::unique_ptr<queryeval::SearchIterator> iterator = searchContext->createIterator(nullptr, true);
std::unique_ptr<ResultSet> results = performSearch(*iterator, _attrPtr->getNumDocs());
diff --git a/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp b/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp
index f9e6340560f..0e7308d0ede 100644
--- a/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp
+++ b/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp
@@ -426,7 +426,7 @@ BitVectorTest::checkSearch(AttributePtr v,
bool checkStride)
{
TermFieldMatchData md;
- sc->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(search::queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
checkSearch(std::move(v), std::move(sb), md,
expFirstDocId, expLastDocId, expDocFreq, weights,
diff --git a/searchlib/src/tests/attribute/direct_multi_term_blueprint/direct_multi_term_blueprint_test.cpp b/searchlib/src/tests/attribute/direct_multi_term_blueprint/direct_multi_term_blueprint_test.cpp
index 87b771af8e6..1d66c59d2c9 100644
--- a/searchlib/src/tests/attribute/direct_multi_term_blueprint/direct_multi_term_blueprint_test.cpp
+++ b/searchlib/src/tests/attribute/direct_multi_term_blueprint/direct_multi_term_blueprint_test.cpp
@@ -222,7 +222,6 @@ public:
} else {
validate_posting_lists<StringKey>(*store);
}
- blueprint->setDocIdLimit(doc_id_limit);
if (need_term_field_match_data) {
tfmd.needs_normal_features();
} else {
@@ -263,8 +262,9 @@ public:
add_term(value);
}
}
- std::unique_ptr<SearchIterator> create_leaf_search(bool strict = true) const {
- return blueprint->createLeafSearch(tfmda, strict);
+ std::unique_ptr<SearchIterator> create_leaf_search(bool strict = true) {
+ blueprint->basic_plan(strict, doc_id_limit);
+ return blueprint->createLeafSearch(tfmda);
}
vespalib::string resolve_iterator_with_unpack() const {
if (in_operator) {
diff --git a/searchlib/src/tests/attribute/enumeratedsave/enumeratedsave_test.cpp b/searchlib/src/tests/attribute/enumeratedsave/enumeratedsave_test.cpp
index df58e839180..0795d85e4a2 100644
--- a/searchlib/src/tests/attribute/enumeratedsave/enumeratedsave_test.cpp
+++ b/searchlib/src/tests/attribute/enumeratedsave/enumeratedsave_test.cpp
@@ -665,7 +665,7 @@ EnumeratedSaveTest::testReload(AttributePtr v0,
TermFieldMatchData md;
SearchContextPtr sc = getSearch<VectorType>(as<VectorType>(v));
- sc->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(search::queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
sb->initFullRange();
sb->seek(1u);
diff --git a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp
index 93ae9cb13cb..41ec377dece 100644
--- a/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp
+++ b/searchlib/src/tests/attribute/imported_search_context/imported_search_context_test.cpp
@@ -271,7 +271,7 @@ TEST_F("Non-strict iterator unpacks target match data for weighted set hit", Wse
TEST_F("Strict iterator is marked as strict", Fixture) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -280,7 +280,7 @@ TEST_F("Strict iterator is marked as strict", Fixture) {
TEST_F("Non-strict blueprint with high hit rate is strict", Fixture(false, FastSearchConfig::ExplicitlyEnabled)) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::createForTest(false, 0.02));
+ ctx->fetchPostings(queryeval::ExecuteInfo::createForTest(0.02), false);
TermFieldMatchData match;
auto iter = f.create_iterator(*ctx, match, false);
@@ -289,7 +289,7 @@ TEST_F("Non-strict blueprint with high hit rate is strict", Fixture(false, FastS
TEST_F("Non-strict blueprint with low hit rate is non-strict", Fixture(false, FastSearchConfig::ExplicitlyEnabled)) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::createForTest(false, 0.01));
+ ctx->fetchPostings(queryeval::ExecuteInfo::createForTest(0.01), false);
TermFieldMatchData match;
auto iter = f.create_iterator(*ctx, match, false);
@@ -314,7 +314,7 @@ SingleValueFixture::~SingleValueFixture() = default;
TEST_F("Strict iterator seeks to first available hit LID", SingleValueFixture) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -340,7 +340,7 @@ TEST_F("Strict iterator seeks to first available hit LID", SingleValueFixture) {
TEST_F("Strict iterator unpacks target match data for single value hit", SingleValueFixture) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -352,7 +352,7 @@ TEST_F("Strict iterator unpacks target match data for single value hit", SingleV
TEST_F("Strict iterator unpacks target match data for array hit", ArrayValueFixture) {
auto ctx = f.create_context(word_term("1234"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -364,7 +364,7 @@ TEST_F("Strict iterator unpacks target match data for array hit", ArrayValueFixt
TEST_F("Strict iterator unpacks target match data for weighted set hit", WsetValueFixture) {
auto ctx = f.create_context(word_term("foo"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -375,7 +375,7 @@ TEST_F("Strict iterator unpacks target match data for weighted set hit", WsetVal
TEST_F("Strict iterator handles seek outside of LID space", ArrayValueFixture) {
auto ctx = f.create_context(word_term("1234"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
@@ -407,7 +407,7 @@ TEST_F("matches(weight) performs GID mapping and forwards to target attribute",
TEST_F("Multiple iterators can be created from the same context", SingleValueFixture) {
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match1;
auto iter1 = f.create_strict_iterator(*ctx, match1);
@@ -490,7 +490,7 @@ TEST_F("Bit vector from search cache is used if found", SearchCacheFixture)
f.imported_attr->getSearchCache()->insert("5678",
makeSearchCacheEntry({2, 6}, f.get_imported_attr()->getNumDocs()));
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
TEST_DO(f.assertSearch({2, 6}, *iter)); // Note: would be {3, 5} if cache was not used
@@ -509,7 +509,7 @@ TEST_F("Entry is inserted into search cache if bit vector posting list is used",
{
EXPECT_EQUAL(0u, f.imported_attr->getSearchCache()->size());
auto ctx = f.create_context(word_term("5678"));
- ctx->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ ctx->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData match;
auto iter = f.create_strict_iterator(*ctx, match);
TEST_DO(f.assertSearch({3, 5}, *iter));
diff --git a/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp b/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp
index ed91cefd35c..8da9b4466d7 100644
--- a/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp
+++ b/searchlib/src/tests/attribute/postinglistattribute/postinglistattribute_test.cpp
@@ -378,7 +378,7 @@ PostingListAttributeTest::assertSearch(const std::string &exp, StringAttribute &
{
TermFieldMatchData md;
SearchContextPtr sc = getSearch<StringAttribute>(sa);
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
bool retval = true;
EXPECT_TRUE(assertIterator(exp, *sb)) << (retval = false, "");
@@ -391,7 +391,7 @@ PostingListAttributeTest::assertSearch(const std::string &exp, StringAttribute &
{
TermFieldMatchData md;
SearchContextPtr sc = getSearch<StringAttribute, std::string>(sa, key, false);
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
bool retval = true;
EXPECT_TRUE(assertIterator(exp, *sb, &md)) << (retval = false, "");
@@ -403,7 +403,7 @@ PostingListAttributeTest::assertSearch(const std::string &exp, IntegerAttribute
{
TermFieldMatchData md;
SearchContextPtr sc = getSearch<IntegerAttribute, int32_t>(ia, key, false);
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
bool retval = true;
EXPECT_TRUE(assertIterator(exp, *sb, &md)) << (retval = false, "");
@@ -497,7 +497,7 @@ PostingListAttributeTest::checkSearch(bool useBitVector, bool need_unpack, bool
{
SearchContextPtr sc = getSearch(vec, term, false, attribute::SearchContextParams().useBitVector(useBitVector));
EXPECT_FALSE( ! sc );
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
auto est = sc->calc_hit_estimate();
uint32_t est_hits = est.est_hits();
EXPECT_FALSE(est.is_unknown());
@@ -912,7 +912,7 @@ PostingListAttributeTest::testMinMax(AttributePtr &ptr1, uint32_t trimmed)
{
TermFieldMatchData md;
SearchContextPtr sc = getSearch<VectorType>(as<VectorType>(ptr1));
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = sc->createIterator(&md, true);
sb->initFullRange();
@@ -937,7 +937,7 @@ PostingListAttributeTest::testMinMax(AttributePtr &ptr1, uint32_t trimmed)
EXPECT_EQ(1u, sb->getDocId());
sc = getSearch2<VectorType>(as<VectorType>(ptr1));
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
sb = sc->createIterator(&md, true);
sb->initFullRange();
diff --git a/searchlib/src/tests/attribute/searchable/attribute_searchable_adapter_test.cpp b/searchlib/src/tests/attribute/searchable/attribute_searchable_adapter_test.cpp
index 3b346601245..bc360e635c1 100644
--- a/searchlib/src/tests/attribute/searchable/attribute_searchable_adapter_test.cpp
+++ b/searchlib/src/tests/attribute/searchable/attribute_searchable_adapter_test.cpp
@@ -223,8 +223,9 @@ Result do_search(IAttributeManager &attribute_manager, const Node &node, bool st
Blueprint::UP bp = source.createBlueprint(requestContext, FieldSpec(field, fieldId, handle), node);
ASSERT_TRUE(bp);
Result result(bp->getState().estimate().estHits, bp->getState().estimate().empty);
- bp->fetchPostings(queryeval::ExecuteInfo::createForTest(strict));
- SearchIterator::UP iterator = bp->createSearch(*match_data, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP iterator = bp->createSearch(*match_data);
ASSERT_TRUE(iterator);
iterator->initRange(1, num_docs);
extract_posting_info(result, iterator->getPostingInfo());
diff --git a/searchlib/src/tests/attribute/searchable/attribute_weighted_set_blueprint_test.cpp b/searchlib/src/tests/attribute/searchable/attribute_weighted_set_blueprint_test.cpp
index a8630ea569e..7a794795cce 100644
--- a/searchlib/src/tests/attribute/searchable/attribute_weighted_set_blueprint_test.cpp
+++ b/searchlib/src/tests/attribute/searchable/attribute_weighted_set_blueprint_test.cpp
@@ -111,8 +111,9 @@ struct WS {
FieldSpecList fields;
fields.add(FieldSpec(field, fieldId, handle, ac.getAttribute(field)->getIsFilter()));
queryeval::Blueprint::UP bp = searchable.createBlueprint(requestContext, fields, *node);
- bp->fetchPostings(queryeval::ExecuteInfo::createForTest(strict));
- SearchIterator::UP sb = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP sb = bp->createSearch(*md);
return sb;
}
bool isWeightedSetTermSearch(Searchable &searchable, const std::string &field, bool strict) const {
@@ -127,8 +128,9 @@ struct WS {
FieldSpecList fields;
fields.add(FieldSpec(field, fieldId, handle));
queryeval::Blueprint::UP bp = searchable.createBlueprint(requestContext, fields, *node);
- bp->fetchPostings(queryeval::ExecuteInfo::createForTest(strict));
- SearchIterator::UP sb = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP sb = bp->createSearch(*md);
FakeResult result;
sb->initRange(1, 10);
for (uint32_t docId = 1; docId < 10; ++docId) {
diff --git a/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp b/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp
index 50f7d170afc..4a7cc3984dd 100644
--- a/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp
+++ b/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp
@@ -127,9 +127,9 @@ do_search(const Node &node, IAttributeManager &attribute_manager, bool expect_at
} else {
EXPECT_TRUE(result->get_attribute_search_context() == nullptr);
}
- result->fetchPostings(queryeval::ExecuteInfo::TRUE);
- result->setDocIdLimit(DOCID_LIMIT);
- SearchIterator::UP iterator = result->createSearch(*md, true);
+ result->basic_plan(true, DOCID_LIMIT);
+ result->fetchPostings(queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP iterator = result->createSearch(*md);
assert((bool)iterator);
iterator->initRange(1, DOCID_LIMIT);
EXPECT_TRUE(!iterator->seek(1));
@@ -313,8 +313,8 @@ public:
~BlueprintFactoryFixture() {}
Blueprint::UP create_blueprint(const Node& term) {
auto result = source.createBlueprint(request_ctx, FieldSpec(attr_name, 0, 0), term);
- result->fetchPostings(queryeval::ExecuteInfo::TRUE);
- result->setDocIdLimit(DOCID_LIMIT);
+ result->basic_plan(true, DOCID_LIMIT);
+ result->fetchPostings(queryeval::ExecuteInfo::FULL);
return result;
}
void expect_document_weight_attribute() {
@@ -325,14 +325,14 @@ public:
}
void expect_filter_search(const SimpleResult& upper, const SimpleResult& lower, const Node& term) {
auto blueprint = create_blueprint(term);
- auto upper_itr = blueprint->createFilterSearch(true, BFC::UPPER_BOUND);
- auto lower_itr = blueprint->createFilterSearch(true, BFC::LOWER_BOUND);
+ auto upper_itr = blueprint->createFilterSearch(BFC::UPPER_BOUND);
+ auto lower_itr = blueprint->createFilterSearch(BFC::LOWER_BOUND);
EXPECT_EQ(upper, SimpleResult().search(*upper_itr, DOCID_LIMIT));
EXPECT_EQ(lower, SimpleResult().search(*lower_itr, DOCID_LIMIT));
}
void expect_filter_wrapper(const Node& term) {
auto blueprint = create_blueprint(term);
- auto itr = blueprint->createFilterSearch(true, BFC::UPPER_BOUND);
+ auto itr = blueprint->createFilterSearch(BFC::UPPER_BOUND);
downcast<FilterWrapper>(*itr);
}
};
diff --git a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp
index 77acbe046ca..87e6b2320fd 100644
--- a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp
+++ b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp
@@ -241,7 +241,7 @@ protected:
// test search iterator unpacking
void fillForSearchIteratorUnpackingTest(IntegerAttribute * ia, bool extra);
void testSearchIteratorUnpacking(const AttributePtr & ptr, SearchContext & sc, bool extra, bool strict) {
- sc.fetchPostings(queryeval::ExecuteInfo::createForTest(strict));
+ sc.fetchPostings(queryeval::ExecuteInfo::FULL, true);
for (bool withElementId : {false, true}) {
testSearchIteratorUnpacking(ptr, sc, extra, strict, withElementId);
}
@@ -469,7 +469,7 @@ template <typename V, typename T>
ResultSetPtr
SearchContextTest::performSearch(const V & vec, const T & term)
{
- return performSearch(queryeval::ExecuteInfo::TRUE, vec, term, TermType::WORD);
+ return performSearch(queryeval::ExecuteInfo::FULL, vec, term, TermType::WORD);
}
template <typename V, typename T>
@@ -478,7 +478,7 @@ SearchContextTest::performSearch(const queryeval::ExecuteInfo & executeInfo, con
{
TermFieldMatchData dummy;
SearchContextPtr sc = getSearch(vec, term, termType);
- sc->fetchPostings(executeInfo);
+ sc->fetchPostings(executeInfo, true);
SearchBasePtr sb = sc->createIterator(&dummy, true);
ResultSetPtr rs = performSearch(*sb, vec.getNumDocs());
return rs;
@@ -504,7 +504,7 @@ void
SearchContextTest::performSearch(const V & vec, const vespalib::string & term,
const DocSet & expected, TermType termType)
{
- performSearch(queryeval::ExecuteInfo::TRUE, vec, term, expected, termType);
+ performSearch(queryeval::ExecuteInfo::FULL, vec, term, expected, termType);
}
void
@@ -547,7 +547,7 @@ SearchContextTest::testFind(const PostingList<V, T> & pl, bool verify_hit_estima
EXPECT_EQ(exp_est.est_hits(), act_est.est_hits());
EXPECT_EQ(exp_est.is_unknown(), act_est.is_unknown());
}
- sc->fetchPostings(queryeval::ExecuteInfo::TRUE);
+ sc->fetchPostings(queryeval::ExecuteInfo::FULL, true);
TermFieldMatchData dummy;
SearchBasePtr sb = sc->createIterator(&dummy, true);
ResultSetPtr rs = performSearch(*sb, pl.getAttribute().getNumDocs());
@@ -676,7 +676,7 @@ public:
~Verifier() override;
SearchIterator::UP
create(bool strict) const override {
- _sc->fetchPostings(queryeval::ExecuteInfo::createForTest(strict));
+ _sc->fetchPostings(queryeval::ExecuteInfo::FULL, strict);
return _sc->createIterator(&_dummy, strict);
}
private:
@@ -784,7 +784,7 @@ SearchContextTest::testStrictSearchIterator(SearchContext & threeHits,
{
TermFieldMatchData dummy;
{ // search for value with 3 hits
- threeHits.fetchPostings(queryeval::ExecuteInfo::TRUE);
+ threeHits.fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = threeHits.createIterator(&dummy, true);
sb->initRange(1, threeHits.attribute().getCommittedDocIdLimit());
EXPECT_TRUE(typeTester.matches(*sb));
@@ -805,7 +805,7 @@ SearchContextTest::testStrictSearchIterator(SearchContext & threeHits,
}
{ // search for value with no hits
- noHits.fetchPostings(queryeval::ExecuteInfo::TRUE);
+ noHits.fetchPostings(queryeval::ExecuteInfo::FULL, true);
SearchBasePtr sb = noHits.createIterator(&dummy, true);
sb->initRange(1, noHits.attribute().getCommittedDocIdLimit());
ASSERT_TRUE(typeTester.matches(*sb));
@@ -823,7 +823,7 @@ SearchContextTest::testNonStrictSearchIterator(SearchContext & threeHits,
{
TermFieldMatchData dummy;
{ // search for value with three hits
- threeHits.fetchPostings(queryeval::ExecuteInfo::FALSE);
+ threeHits.fetchPostings(queryeval::ExecuteInfo::FULL, false);
SearchBasePtr sb = threeHits.createIterator(&dummy, false);
sb->initRange(1, threeHits.attribute().getCommittedDocIdLimit());
EXPECT_TRUE(typeTester.matches(*sb));
@@ -841,7 +841,7 @@ SearchContextTest::testNonStrictSearchIterator(SearchContext & threeHits,
EXPECT_TRUE(sb->getDocId() == 5u || sb->isAtEnd());
}
{ // search for value with no hits
- noHits.fetchPostings(queryeval::ExecuteInfo::FALSE);
+ noHits.fetchPostings(queryeval::ExecuteInfo::FULL, false);
SearchBasePtr sb = noHits.createIterator(&dummy, false);
sb->initRange(1, threeHits.attribute().getCommittedDocIdLimit());
@@ -1118,7 +1118,7 @@ SearchContextTest::performRangeSearch(const VectorType & vec, const vespalib::st
{
for (size_t num_threads : {1,3}) {
vespalib::SimpleThreadBundle thread_bundle(num_threads);
- auto executeInfo = queryeval::ExecuteInfo::create(true, 1.0, vespalib::Doom::never(), thread_bundle);
+ auto executeInfo = queryeval::ExecuteInfo::create(1.0, vespalib::Doom::never(), thread_bundle);
performSearch(executeInfo, vec, term, expected, TermType::WORD);
}
}
diff --git a/searchlib/src/tests/diskindex/diskindex/diskindex_test.cpp b/searchlib/src/tests/diskindex/diskindex/diskindex_test.cpp
index 552ce0e2f0b..d298dc967e5 100644
--- a/searchlib/src/tests/diskindex/diskindex/diskindex_test.cpp
+++ b/searchlib/src/tests/diskindex/diskindex/diskindex_test.cpp
@@ -313,49 +313,53 @@ DiskIndexTest::requireThatBlueprintCanCreateSearchIterators()
auto upper_bound = Blueprint::FilterConstraint::UPPER_BOUND;
{ // bit vector due to isFilter
b = _index->createBlueprint(_requestContext, FieldSpec("f2", 0, 0, true), makeTerm("w2"));
- b->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
+ b->basic_plan(true, 1000);
+ b->fetchPostings(search::queryeval::ExecuteInfo::FULL);
auto& leaf_b = dynamic_cast<LeafBlueprint&>(*b);
- s = leaf_b.createLeafSearch(mda, true);
+ s = leaf_b.createLeafSearch(mda);
EXPECT_TRUE(dynamic_cast<BitVectorIterator *>(s.get()) != NULL);
EXPECT_EQ(result_f2_w2, SimpleResult().search(*s));
- EXPECT_EQ(result_f2_w2, SimpleResult().search(*leaf_b.createFilterSearch(true, upper_bound)));
+ EXPECT_EQ(result_f2_w2, SimpleResult().search(*leaf_b.createFilterSearch(upper_bound)));
}
{ // bit vector due to no ranking needed
b = _index->createBlueprint(_requestContext, FieldSpec("f2", 0, 0, false), makeTerm("w2"));
- b->fetchPostings(ExecuteInfo::TRUE);
+ b->basic_plan(true, 1000);
+ b->fetchPostings(ExecuteInfo::FULL);
auto& leaf_b = dynamic_cast<LeafBlueprint&>(*b);
- s = leaf_b.createLeafSearch(mda, true);
+ s = leaf_b.createLeafSearch(mda);
EXPECT_FALSE(dynamic_cast<BitVectorIterator *>(s.get()) != NULL);
TermFieldMatchData md2;
md2.tagAsNotNeeded();
TermFieldMatchDataArray mda2;
mda2.add(&md2);
EXPECT_TRUE(mda2[0]->isNotNeeded());
- s = (dynamic_cast<LeafBlueprint *>(b.get()))->createLeafSearch(mda2, true);
+ s = (dynamic_cast<LeafBlueprint *>(b.get()))->createLeafSearch(mda2);
EXPECT_TRUE(dynamic_cast<BitVectorIterator *>(s.get()) != NULL);
EXPECT_EQ(result_f2_w2, SimpleResult().search(*s));
- EXPECT_EQ(result_f2_w2, SimpleResult().search(*leaf_b.createFilterSearch(true, upper_bound)));
+ EXPECT_EQ(result_f2_w2, SimpleResult().search(*leaf_b.createFilterSearch(upper_bound)));
}
{ // fake bit vector
b = _index->createBlueprint(_requestContext, FieldSpec("f1", 0, 0, true), makeTerm("w2"));
// std::cerr << "BP = " << typeid(*b).name() << std::endl;
- b->fetchPostings(ExecuteInfo::TRUE);
+ b->basic_plan(true, 1000);
+ b->fetchPostings(ExecuteInfo::FULL);
auto& leaf_b = dynamic_cast<LeafBlueprint&>(*b);
- s = leaf_b.createLeafSearch(mda, true);
+ s = leaf_b.createLeafSearch(mda);
// std::cerr << "SI = " << typeid(*s).name() << std::endl;
EXPECT_TRUE((dynamic_cast<BooleanMatchIteratorWrapper *>(s.get()) != NULL) ||
dynamic_cast<EmptySearch *>(s.get()));
EXPECT_EQ(result_f1_w2, SimpleResult().search(*s));
- EXPECT_EQ(result_f1_w2, SimpleResult().search(*leaf_b.createFilterSearch(true, upper_bound)));
+ EXPECT_EQ(result_f1_w2, SimpleResult().search(*leaf_b.createFilterSearch(upper_bound)));
}
{ // posting list iterator
b = _index->createBlueprint(_requestContext, FieldSpec("f1", 0, 0), makeTerm("w1"));
- b->fetchPostings(ExecuteInfo::TRUE);
+ b->basic_plan(true, 1000);
+ b->fetchPostings(ExecuteInfo::FULL);
auto& leaf_b = dynamic_cast<LeafBlueprint&>(*b);
- s = leaf_b.createLeafSearch(mda, true);
+ s = leaf_b.createLeafSearch(mda);
ASSERT_TRUE((dynamic_cast<ZcRareWordPosOccIterator<true, false> *>(s.get()) != NULL));
EXPECT_EQ(result_f1_w1, SimpleResult().search(*s));
- EXPECT_EQ(result_f1_w1, SimpleResult().search(*leaf_b.createFilterSearch(true, upper_bound)));
+ EXPECT_EQ(result_f1_w1, SimpleResult().search(*leaf_b.createFilterSearch(upper_bound)));
}
}
diff --git a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
index 31e80b98e57..1b51ba90f7c 100644
--- a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
+++ b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp
@@ -228,8 +228,9 @@ verifyResult(const FakeResult &expect,
EXPECT_EQ(expect.inspect().size(), result->getState().estimate().estHits);
EXPECT_EQ(expect.inspect().empty(), result->getState().estimate().empty);
- result->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
- SearchIterator::UP search = result->createSearch(*match_data, true);
+ result->basic_plan(true, 100);
+ result->fetchPostings(search::queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP search = result->createSearch(*match_data);
bool valid_search = search.get() != 0;
EXPECT_TRUE(valid_search);
if (!valid_search) {
@@ -256,7 +257,7 @@ verifyResult(const FakeResult &expect,
using FilterConstraint = Blueprint::FilterConstraint;
for (auto constraint : { FilterConstraint::LOWER_BOUND, FilterConstraint::UPPER_BOUND }) {
constexpr uint32_t docid_limit = 10u;
- auto filter_search = result->createFilterSearch(true, constraint);
+ auto filter_search = result->createFilterSearch(constraint);
auto act_simple = SimpleResult().search(*filter_search, docid_limit);
if (constraint == FilterConstraint::LOWER_BOUND) {
EXPECT_TRUE(exp_simple.contains(act_simple)) << (success = false, "");
@@ -522,8 +523,9 @@ TEST(MemoryIndexTest, require_that_we_can_fake_bit_vector)
Blueprint::UP res = searchable.createBlueprint(requestContext, fields, makeTerm(foo));
EXPECT_TRUE(res);
- res->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
- SearchIterator::UP search = res->createSearch(*match_data, true);
+ res->basic_plan(true, 100);
+ res->fetchPostings(search::queryeval::ExecuteInfo::FULL);
+ SearchIterator::UP search = res->createSearch(*match_data);
EXPECT_TRUE(search);
EXPECT_TRUE(dynamic_cast<BooleanMatchIteratorWrapper *>(search.get()) != nullptr);
search->initFullRange();
diff --git a/searchlib/src/tests/nearsearch/nearsearch_test.cpp b/searchlib/src/tests/nearsearch/nearsearch_test.cpp
index 6f7cf85258b..4011366c7a1 100644
--- a/searchlib/src/tests/nearsearch/nearsearch_test.cpp
+++ b/searchlib/src/tests/nearsearch/nearsearch_test.cpp
@@ -229,11 +229,10 @@ Test::testNearSearch(MyQuery &query, uint32_t matchId)
near_b->addChild(query.getTerm(i).make_blueprint(fieldId, i));
}
bp->setDocIdLimit(1000);
- auto opts = search::queryeval::Blueprint::Options::all();
- bp = search::queryeval::Blueprint::optimize_and_sort(std::move(bp), true, opts);
- bp->fetchPostings(search::queryeval::ExecuteInfo::TRUE);
+ bp = search::queryeval::Blueprint::optimize_and_sort(std::move(bp));
+ bp->fetchPostings(search::queryeval::ExecuteInfo::FULL);
search::fef::MatchData::UP md(layout.createMatchData());
- search::queryeval::SearchIterator::UP near = bp->createSearch(*md, true);
+ search::queryeval::SearchIterator::UP near = bp->createSearch(*md);
near->initFullRange();
bool foundMatch = false;
for (near->seek(1u); ! near->isAtEnd(); near->seek(near->getDocId() + 1)) {
diff --git a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp
index 968e006622f..266dc6f8652 100644
--- a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp
+++ b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp
@@ -17,8 +17,6 @@ using namespace search::fef;
namespace {
-auto opts = Blueprint::Options::all();
-
//-----------------------------------------------------------------------------
class MyOr : public IntermediateBlueprint
@@ -45,19 +43,14 @@ public:
std::sort(children.begin(), children.end(), TieredGreaterEstimate());
}
- bool inheritStrict(size_t i) const override {
- (void) i;
- return true;
- }
-
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, MatchData &md) const override
+ MatchData &md) const override
{
- return std::make_unique<MySearch>("or", std::move(subSearches), &md, strict);
+ return std::make_unique<MySearch>("or", std::move(subSearches), &md, strict());
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
static MyOr& create() { return *(new MyOr()); }
MyOr& add(Blueprint *n) { addChild(UP(n)); return *this; }
@@ -71,9 +64,9 @@ private:
public:
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, MatchData &md) const override
+ MatchData &md) const override
{
- return std::make_unique<MySearch>("or", std::move(subSearches), &md, strict);
+ return std::make_unique<MySearch>("or", std::move(subSearches), &md, strict());
}
static OtherOr& create() { return *(new OtherOr()); }
@@ -95,15 +88,11 @@ public:
return {};
}
- bool inheritStrict(size_t i) const override {
- return (i == 0);
- }
-
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, MatchData &md) const override
+ MatchData &md) const override
{
- return std::make_unique<MySearch>("and", std::move(subSearches), &md, strict);
+ return std::make_unique<MySearch>("and", std::move(subSearches), &md, strict());
}
static MyAnd& create() { return *(new MyAnd()); }
@@ -118,9 +107,9 @@ private:
public:
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, MatchData &md) const override
+ MatchData &md) const override
{
- return std::make_unique<MySearch>("and", std::move(subSearches), &md, strict);
+ return std::make_unique<MySearch>("and", std::move(subSearches), &md, strict());
}
static OtherAnd& create() { return *(new OtherAnd()); }
@@ -133,9 +122,9 @@ class OtherAndNot : public AndNotBlueprint
public:
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, MatchData &md) const override
+ MatchData &md) const override
{
- return std::make_unique<MySearch>("andnot", std::move(subSearches), &md, strict);
+ return std::make_unique<MySearch>("andnot", std::move(subSearches), &md, strict());
}
static OtherAndNot& create() { return *(new OtherAndNot()); }
@@ -153,11 +142,11 @@ struct MyTerm : SimpleLeafBlueprint {
FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
return default_flow_stats(docid_limit, getState().estimate().estHits, 0);
}
- SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const override {
+ SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &) const override {
return {};
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
@@ -187,8 +176,9 @@ public:
SearchIterator::UP
Fixture::create(const Blueprint &blueprint)
{
- const_cast<Blueprint &>(blueprint).fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = blueprint.createSearch(*_md, true);
+ const_cast<Blueprint &>(blueprint).null_plan(true, 1000);
+ const_cast<Blueprint &>(blueprint).fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = blueprint.createSearch(*_md);
MySearch::verifyAndInfer(search.get(), *_md);
return search;
}
@@ -453,7 +443,7 @@ TEST_F("testChildAndNotCollapsing", Fixture)
);
TEST_DO(f.check_not_equal(*sorted, *unsorted));
unsorted->setDocIdLimit(1000);
- unsorted = Blueprint::optimize_and_sort(std::move(unsorted), true, opts);
+ unsorted = Blueprint::optimize_and_sort(std::move(unsorted));
TEST_DO(f.check_equal(*sorted, *unsorted));
}
@@ -493,7 +483,7 @@ TEST_F("testChildAndCollapsing", Fixture)
TEST_DO(f.check_not_equal(*sorted, *unsorted));
unsorted->setDocIdLimit(1000);
- unsorted = Blueprint::optimize_and_sort(std::move(unsorted), true, opts);
+ unsorted = Blueprint::optimize_and_sort(std::move(unsorted));
TEST_DO(f.check_equal(*sorted, *unsorted));
}
@@ -534,7 +524,7 @@ TEST_F("testChildOrCollapsing", Fixture)
unsorted->setDocIdLimit(1000);
// we sort non-strict here since a strict OR does not have a
// deterministic sort order.
- unsorted = Blueprint::optimize_and_sort(std::move(unsorted), false, opts);
+ unsorted = Blueprint::optimize_and_sort(std::move(unsorted), false);
TEST_DO(f.check_equal(*sorted, *unsorted));
}
@@ -578,7 +568,7 @@ TEST_F("testChildSorting", Fixture)
TEST_DO(f.check_not_equal(*sorted, *unsorted));
unsorted->setDocIdLimit(1000);
- unsorted = Blueprint::optimize_and_sort(std::move(unsorted), true, opts);
+ unsorted = Blueprint::optimize_and_sort(std::move(unsorted));
TEST_DO(f.check_equal(*sorted, *unsorted));
}
diff --git a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp
index 6b3c068cd4d..9338436348b 100644
--- a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp
+++ b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp
@@ -55,15 +55,13 @@ struct WeightOrder {
};
struct RememberExecuteInfo : public MyLeaf {
- bool is_strict;
double hit_rate;
- RememberExecuteInfo() : MyLeaf(), is_strict(false), hit_rate(0.0) {}
- RememberExecuteInfo(FieldSpecBaseList fields) : MyLeaf(std::move(fields)), is_strict(false), hit_rate(0.0) {}
+ RememberExecuteInfo() : MyLeaf(), hit_rate(0.0) {}
+ RememberExecuteInfo(FieldSpecBaseList fields) : MyLeaf(std::move(fields)), hit_rate(0.0) {}
void fetchPostings(const ExecuteInfo &execInfo) override {
LeafBlueprint::fetchPostings(execInfo);
- is_strict = execInfo.is_strict();
hit_rate = execInfo.hit_rate();
}
};
@@ -75,16 +73,19 @@ bool got_global_filter(Blueprint &b) {
return (static_cast<MyLeaf &>(b)).got_global_filter();
}
-void check_sort_order(IntermediateBlueprint &self, BlueprintVector children, std::vector<size_t> order) {
+void check_sort_order_and_strictness(std::unique_ptr<IntermediateBlueprint> self, bool self_strict, BlueprintVector children, std::vector<size_t> order, std::vector<bool> strict) {
ASSERT_EQUAL(children.size(), order.size());
+ ASSERT_EQUAL(children.size(), strict.size());
std::vector<const Blueprint *> unordered;
- for (const auto & child: children) {
+ for (auto &&child: children) {
unordered.push_back(child.get());
+ self->addChild(std::move(child));
}
- // TODO: sort by cost (requires both setDocIdLimit and optimize to be called)
- self.sort(children, true, false);
- for (size_t i = 0; i < children.size(); ++i) {
- EXPECT_EQUAL(children[i].get(), unordered[order[i]]);
+ self->basic_plan(self_strict, 1000);
+ for (size_t i = 0; i < self->childCnt(); ++i) {
+ const auto &child = self->getChild(i);
+ EXPECT_EQUAL(&child, unordered[order[i]]);
+ EXPECT_EQUAL(child.strict(), strict[i]);
}
}
@@ -126,18 +127,18 @@ TEST("test AndNot Blueprint") {
EXPECT_EQUAL(false, got_global_filter(a.getChild(0)));
EXPECT_EQUAL(true, got_global_filter(a.getChild(1)));
}
- check_sort_order(b, createLeafs({10, 20, 40, 30}), {0, 2, 3, 1});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(false, b.inheritStrict(1));
- EXPECT_EQUAL(false, b.inheritStrict(2));
- EXPECT_EQUAL(false, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<AndNotBlueprint>(), false,
+ createLeafs({10, 20, 40, 30}), {0, 2, 3, 1},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<AndNotBlueprint>(), true,
+ createLeafs({10, 20, 40, 30}), {0, 2, 3, 1},
+ {true, false, false, false});
// createSearch tested by iterator unit test
}
template <typename BP>
void optimize(std::unique_ptr<BP> &ref, bool strict) {
- auto opts = Blueprint::Options::all();
- auto optimized = Blueprint::optimize_and_sort(std::move(ref), strict, opts);
+ auto optimized = Blueprint::optimize_and_sort(std::move(ref), strict);
ref.reset(dynamic_cast<BP*>(optimized.get()));
ASSERT_TRUE(ref);
optimized.release();
@@ -151,11 +152,11 @@ TEST("test And propagates updated histestimate") {
bp->addChild(ap(MyLeafSpec(2000).create<RememberExecuteInfo>()->setSourceId(2)));
bp->setDocIdLimit(5000);
optimize(bp, true);
- bp->fetchPostings(ExecuteInfo::TRUE);
+ bp->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL(3u, bp->childCnt());
for (uint32_t i = 0; i < bp->childCnt(); i++) {
const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i));
- EXPECT_EQUAL((i == 0), child.is_strict);
+ EXPECT_EQUAL((i == 0), child.strict());
}
EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).hit_rate);
EXPECT_EQUAL(1.0/250, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).hit_rate);
@@ -170,25 +171,25 @@ TEST("test Or propagates updated histestimate") {
bp->addChild(ap(MyLeafSpec(800).create<RememberExecuteInfo>()->setSourceId(2)));
bp->addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2)));
bp->setDocIdLimit(5000);
- // NOTE: use non-strict OR ordering since strict OR ordering is non-deterministic
- optimize(bp, false);
//--- execute info when non-strict:
- bp->fetchPostings(ExecuteInfo::FALSE);
+ optimize(bp, false);
+ bp->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL(4u, bp->childCnt());
for (uint32_t i = 0; i < bp->childCnt(); i++) {
const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i));
- EXPECT_FALSE(child.is_strict);
+ EXPECT_FALSE(child.strict());
}
EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).hit_rate);
EXPECT_APPROX(0.5, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).hit_rate, 1e-6);
EXPECT_APPROX(0.5*3.0/5.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(2)).hit_rate, 1e-6);
EXPECT_APPROX(0.5*3.0*42.0/(5.0*50.0), dynamic_cast<const RememberExecuteInfo &>(bp->getChild(3)).hit_rate, 1e-6);
//--- execute info when strict:
- bp->fetchPostings(ExecuteInfo::TRUE);
+ optimize(bp, true);
+ bp->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL(4u, bp->childCnt());
for (uint32_t i = 0; i < bp->childCnt(); i++) {
const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i));
- EXPECT_TRUE(child.is_strict);
+ EXPECT_TRUE(child.strict());
}
EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).hit_rate);
EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).hit_rate);
@@ -227,12 +228,12 @@ TEST("test And Blueprint") {
EXPECT_EQUAL(false, got_global_filter(a.getChild(0)));
EXPECT_EQUAL(true, got_global_filter(a.getChild(1)));
}
- check_sort_order(b, createLeafs({20, 40, 10, 30}), {2, 0, 3, 1});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(false, b.inheritStrict(1));
- EXPECT_EQUAL(false, b.inheritStrict(2));
- EXPECT_EQUAL(false, b.inheritStrict(-1));
-
+ check_sort_order_and_strictness(std::make_unique<AndBlueprint>(), false,
+ createLeafs({20, 40, 10, 30}), {2, 0, 3, 1},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<AndBlueprint>(), true,
+ createLeafs({20, 40, 10, 30}), {2, 0, 3, 1},
+ {true, false, false, false});
// createSearch tested by iterator unit test
}
@@ -291,11 +292,12 @@ TEST("test Or Blueprint") {
EXPECT_EQUAL(false, got_global_filter(o.getChild(0)));
EXPECT_EQUAL(true, got_global_filter(o.getChild(o.childCnt() - 1)));
}
- check_sort_order(b, createLeafs({10, 20, 40, 30}), {2, 3, 1, 0});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(true, b.inheritStrict(1));
- EXPECT_EQUAL(true, b.inheritStrict(2));
- EXPECT_EQUAL(true, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<OrBlueprint>(), false,
+ createLeafs({10, 20, 40, 30}), {2, 3, 1, 0},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<OrBlueprint>(), true,
+ createLeafs({10, 20, 40, 30}), {0, 1, 2, 3},
+ {true, true, true, true});
// createSearch tested by iterator unit test
}
@@ -323,11 +325,12 @@ TEST("test Near Blueprint") {
a.addChild(ap(MyLeafSpec(10).addField(1, 1).create()));
EXPECT_EQUAL(0u, a.exposeFields().size());
}
- check_sort_order(b, createLeafs({40, 10, 30, 20}), {1, 3, 2, 0});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(false, b.inheritStrict(1));
- EXPECT_EQUAL(false, b.inheritStrict(2));
- EXPECT_EQUAL(false, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<NearBlueprint>(7), false,
+ createLeafs({40, 10, 30, 20}), {1, 3, 2, 0},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<NearBlueprint>(7), true,
+ createLeafs({40, 10, 30, 20}), {1, 3, 2, 0},
+ {true, false, false, false});
// createSearch tested by iterator unit test
}
@@ -355,11 +358,12 @@ TEST("test ONear Blueprint") {
a.addChild(ap(MyLeafSpec(10).addField(1, 1).create()));
EXPECT_EQUAL(0u, a.exposeFields().size());
}
- check_sort_order(b, createLeafs({20, 10, 40, 30}), {0, 1, 2, 3});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(false, b.inheritStrict(1));
- EXPECT_EQUAL(false, b.inheritStrict(2));
- EXPECT_EQUAL(false, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<ONearBlueprint>(7), false,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<ONearBlueprint>(7), true,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {true, false, false, false});
// createSearch tested by iterator unit test
}
@@ -395,11 +399,12 @@ TEST("test Rank Blueprint") {
EXPECT_EQUAL(false, got_global_filter(a.getChild(0)));
EXPECT_EQUAL(true, got_global_filter(a.getChild(1)));
}
- check_sort_order(b, createLeafs({20, 10, 40, 30}), {0, 1, 2, 3});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(false, b.inheritStrict(1));
- EXPECT_EQUAL(false, b.inheritStrict(2));
- EXPECT_EQUAL(false, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<RankBlueprint>(), false,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<RankBlueprint>(), true,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {true, false, false, false});
// createSearch tested by iterator unit test
}
@@ -451,11 +456,12 @@ TEST("test SourceBlender Blueprint") {
o.addChild(ap(MyLeafSpec(0, true).create()));
EXPECT_EQUAL(0u, a->getState().numFields());
}
- check_sort_order(b, createLeafs({20, 10, 40, 30}), {0, 1, 2, 3});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(true, b.inheritStrict(1));
- EXPECT_EQUAL(true, b.inheritStrict(2));
- EXPECT_EQUAL(true, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<SourceBlenderBlueprint>(*selector), false,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<SourceBlenderBlueprint>(*selector), true,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {true, true, true, true});
// createSearch tested by iterator unit test
}
@@ -573,7 +579,7 @@ optimize_and_compare(Blueprint::UP top, Blueprint::UP expect, bool strict = true
top->setDocIdLimit(1000);
expect->setDocIdLimit(1000);
TEST_DO(compare(*top, *expect, false));
- auto opts = Blueprint::Options::all().sort_by_cost(sort_by_cost);
+ auto opts = Blueprint::Options::default_options().sort_by_cost(sort_by_cost);
top = Blueprint::optimize_and_sort(std::move(top), strict, opts);
TEST_DO(compare(*top, *expect, true));
expect = Blueprint::optimize_and_sort(std::move(expect), strict, opts);
@@ -705,12 +711,11 @@ TEST("test empty root node optimization and safeness") {
//-------------------------------------------------------------------------
auto expect_up = std::make_unique<EmptyBlueprint>();
- auto opts = Blueprint::Options::all();
- compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top1), true, opts), true);
- compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top2), true, opts), true);
- compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top3), true, opts), true);
- compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top4), true, opts), true);
- compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top5), true, opts), true);
+ compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top1)), true);
+ compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top2)), true);
+ compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top3)), true);
+ compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top4)), true);
+ compare(*expect_up, *Blueprint::optimize_and_sort(std::move(top5)), true);
}
TEST("and with one empty child is optimized away") {
@@ -718,8 +723,7 @@ TEST("and with one empty child is optimized away") {
Blueprint::UP top = ap((new SourceBlenderBlueprint(*selector))->
addChild(ap(MyLeafSpec(10).create())).
addChild(addLeafs(std::make_unique<AndBlueprint>(), {{0, true}, 10, 20})));
- auto opts = Blueprint::Options::all();
- top = Blueprint::optimize_and_sort(std::move(top), true, opts);
+ top = Blueprint::optimize_and_sort(std::move(top));
Blueprint::UP expect_up(ap((new SourceBlenderBlueprint(*selector))->
addChild(ap(MyLeafSpec(10).create())).
addChild(std::make_unique<EmptyBlueprint>())));
@@ -896,9 +900,8 @@ TEST("require that replaced blueprints retain source id") {
addChild(ap(MyLeafSpec(30).create()->setSourceId(55)))));
Blueprint::UP expect2_up(ap(MyLeafSpec(30).create()->setSourceId(42)));
//-------------------------------------------------------------------------
- auto opts = Blueprint::Options::all();
- top1_up = Blueprint::optimize_and_sort(std::move(top1_up), true, opts);
- top2_up = Blueprint::optimize_and_sort(std::move(top2_up), true, opts);
+ top1_up = Blueprint::optimize_and_sort(std::move(top1_up));
+ top2_up = Blueprint::optimize_and_sort(std::move(top2_up));
compare(*expect1_up, *top1_up, true);
compare(*expect2_up, *top2_up, true);
EXPECT_EQUAL(13u, top1_up->getSourceId());
@@ -960,11 +963,12 @@ TEST("test WeakAnd Blueprint") {
a.addChild(ap(MyLeafSpec(10).addField(1, 1).create()));
EXPECT_EQUAL(0u, a.exposeFields().size());
}
- check_sort_order(b, createLeafs({20, 10, 40, 30}), {0, 1, 2, 3});
- EXPECT_EQUAL(true, b.inheritStrict(0));
- EXPECT_EQUAL(true, b.inheritStrict(1));
- EXPECT_EQUAL(true, b.inheritStrict(2));
- EXPECT_EQUAL(true, b.inheritStrict(-1));
+ check_sort_order_and_strictness(std::make_unique<WeakAndBlueprint>(1000), false,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {false, false, false, false});
+ check_sort_order_and_strictness(std::make_unique<WeakAndBlueprint>(1000), true,
+ createLeafs({20, 10, 40, 30}), {0, 1, 2, 3},
+ {true, true, true, true});
{
FieldSpec field("foo", 1, 1);
FakeResult x = FakeResult().doc(1).doc(2).doc(5);
@@ -977,8 +981,9 @@ TEST("test WeakAnd Blueprint") {
wa.addTerm(std::make_unique<FakeBlueprint>(field, z), 140);
wa.addTerm(std::make_unique<FakeBlueprint>(field, y), 130);
{
- wa.fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = wa.createSearch(*md, true);
+ wa.basic_plan(true, 1000);
+ wa.fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = wa.createSearch(*md);
EXPECT_TRUE(dynamic_cast<WeakAndSearch*>(search.get()) != nullptr);
auto &s = dynamic_cast<WeakAndSearch&>(*search);
EXPECT_EQUAL(456u, s.getN());
@@ -999,8 +1004,9 @@ TEST("test WeakAnd Blueprint") {
EXPECT_EQUAL(0u, terms[2].maxScore); // NB: not set
}
{
- wa.fetchPostings(ExecuteInfo::FALSE);
- SearchIterator::UP search = wa.createSearch(*md, false);
+ wa.basic_plan(false, 1000);
+ wa.fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = wa.createSearch(*md);
EXPECT_TRUE(dynamic_cast<WeakAndSearch*>(search.get()) != nullptr);
EXPECT_TRUE(search->seek(1));
EXPECT_TRUE(search->seek(2));
@@ -1029,23 +1035,24 @@ TEST("require_that_unpack_of_or_over_multisearch_is_optimized") {
addChild(std::move(child1)).
addChild(std::move(child2))));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
+ top_up->basic_plan(false, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(2)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(1)->tagAsNotNeeded();
md->resolveTermField(3)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::SelectiveUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(4)->tagAsNotNeeded();
md->resolveTermField(6)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::SelectiveUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(5)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::NoUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
}
TEST("require_that_unpack_of_or_is_optimized") {
@@ -1055,16 +1062,17 @@ TEST("require_that_unpack_of_or_is_optimized") {
addChild(ap(MyLeafSpec(20).addField(2,2).create())).
addChild(ap(MyLeafSpec(10).addField(3,3).create()))));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
+ top_up->basic_plan(false, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(2)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::(anonymous namespace)::SelectiveUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(1)->tagAsNotNeeded();
md->resolveTermField(3)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::OrLikeSearch<false, search::queryeval::NoUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
}
TEST("require_that_unpack_of_and_is_optimized") {
@@ -1074,16 +1082,17 @@ TEST("require_that_unpack_of_and_is_optimized") {
addChild(ap(MyLeafSpec(20).addField(2,2).create())).
addChild(ap(MyLeafSpec(10).addField(3,3).create()))));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
+ top_up->basic_plan(false, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(2)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::SelectiveUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(1)->tagAsNotNeeded();
md->resolveTermField(3)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::NoUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
}
TEST("require_that_unpack_optimization_is_honoured_by_parents") {
@@ -1094,16 +1103,17 @@ TEST("require_that_unpack_optimization_is_honoured_by_parents") {
addChild(ap(MyLeafSpec(20).addField(2,2).create())).
addChild(ap(MyLeafSpec(10).addField(3,3).create()))))));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
+ top_up->basic_plan(false, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(2)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::FullUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
md->resolveTermField(1)->tagAsNotNeeded();
md->resolveTermField(3)->tagAsNotNeeded();
EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::NoUnpack>",
- top_up->createSearch(*md, false)->getClassName());
+ top_up->createSearch(*md)->getClassName());
}
namespace {
@@ -1143,8 +1153,9 @@ TEST("require that children does not optimize when parents refuse them to") {
FieldSpec("f2", 2, idxth21), makeTerm("w2")),
1.0)));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
- SearchIterator::UP search = top_up->createSearch(*md, true);
+ top_up->basic_plan(true, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = top_up->createSearch(*md);
EXPECT_EQUAL(strict_equiv_name, normalize_class_name(search->getClassName()));
{
const auto & e = dynamic_cast<const MultiSearch &>(*search);
@@ -1154,7 +1165,7 @@ TEST("require that children does not optimize when parents refuse them to") {
}
md->resolveTermField(12)->tagAsNotNeeded();
- search = top_up->createSearch(*md, true);
+ search = top_up->createSearch(*md);
EXPECT_EQUAL(strict_equiv_name, normalize_class_name(search->getClassName()));
{
const auto & e = dynamic_cast<const MultiSearch &>(*search);
@@ -1181,8 +1192,9 @@ TEST("require_that_unpack_optimization_is_not_overruled_by_equiv") {
addChild(ap(MyLeafSpec(10).addField(3,idxth3).create()))),
1.0)));
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- top_up->fetchPostings(ExecuteInfo::FALSE);
- SearchIterator::UP search = top_up->createSearch(*md, true);
+ top_up->basic_plan(true, 1000);
+ top_up->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = top_up->createSearch(*md);
EXPECT_EQUAL(strict_equiv_name, normalize_class_name(search->getClassName()));
{
const auto & e = dynamic_cast<const MultiSearch &>(*search);
@@ -1191,7 +1203,7 @@ TEST("require_that_unpack_optimization_is_not_overruled_by_equiv") {
}
md->resolveTermField(2)->tagAsNotNeeded();
- search = top_up->createSearch(*md, true);
+ search = top_up->createSearch(*md);
EXPECT_EQUAL(strict_equiv_name, normalize_class_name(search->getClassName()));
{
const auto & e = dynamic_cast<const MultiSearch &>(*search);
@@ -1201,7 +1213,7 @@ TEST("require_that_unpack_optimization_is_not_overruled_by_equiv") {
md->resolveTermField(1)->tagAsNotNeeded();
md->resolveTermField(3)->tagAsNotNeeded();
- search = top_up->createSearch(*md, true);
+ search = top_up->createSearch(*md);
EXPECT_EQUAL(strict_equiv_name, normalize_class_name(search->getClassName()));
{
const auto & e = dynamic_cast<const MultiSearch &>(*search);
@@ -1213,8 +1225,7 @@ TEST("require_that_unpack_optimization_is_not_overruled_by_equiv") {
TEST("require that ANDNOT without children is optimized to empty search") {
Blueprint::UP top_up = std::make_unique<AndNotBlueprint>();
auto expect_up = std::make_unique<EmptyBlueprint>();
- auto opts = Blueprint::Options::all();
- top_up = Blueprint::optimize_and_sort(std::move(top_up), true, opts);
+ top_up = Blueprint::optimize_and_sort(std::move(top_up));
compare(*expect_up, *top_up, true);
}
diff --git a/searchlib/src/tests/queryeval/blueprint/leaf_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/leaf_blueprints_test.cpp
index 44be9fb0fca..cb5473babbd 100644
--- a/searchlib/src/tests/queryeval/blueprint/leaf_blueprints_test.cpp
+++ b/searchlib/src/tests/queryeval/blueprint/leaf_blueprints_test.cpp
@@ -29,8 +29,9 @@ Test::testEmptyBlueprint()
EXPECT_EQUAL(1u, empty.getState().field(0).getFieldId());
EXPECT_EQUAL(11u, empty.getState().field(0).getHandle());
- empty.fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = empty.createSearch(*md, true);
+ empty.basic_plan(true, 100);
+ empty.fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = empty.createSearch(*md);
SimpleResult res;
res.search(*search);
@@ -47,8 +48,9 @@ Test::testSimpleBlueprint()
SimpleBlueprint simple(a);
simple.tag("tag");
EXPECT_EQUAL("tag", simple.tag());
- simple.fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = simple.createSearch(*md, true);
+ simple.basic_plan(true, 100);
+ simple.fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = simple.createSearch(*md);
SimpleResult res;
res.search(*search);
@@ -69,8 +71,9 @@ Test::testFakeBlueprint()
TermFieldHandle handle = 0;
FakeBlueprint orig(FieldSpec("<field>", fieldId, handle), fake);
- orig.fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP search = orig.createSearch(*md, true);
+ orig.basic_plan(true, 100);
+ orig.fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = orig.createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(1u));
EXPECT_EQUAL(10u, search->getDocId());
diff --git a/searchlib/src/tests/queryeval/blueprint/mysearch.h b/searchlib/src/tests/queryeval/blueprint/mysearch.h
index 79c9885bb7d..e3b86a0eb84 100644
--- a/searchlib/src/tests/queryeval/blueprint/mysearch.h
+++ b/searchlib/src/tests/queryeval/blueprint/mysearch.h
@@ -109,9 +109,9 @@ class MyLeaf : public SimpleLeafBlueprint
public:
SearchIterator::UP
- createLeafSearch(const TFMDA &tfmda, bool strict) const override
+ createLeafSearch(const TFMDA &tfmda) const override
{
- return std::make_unique<MySearch>("leaf", tfmda, strict);
+ return std::make_unique<MySearch>("leaf", tfmda, strict());
}
MyLeaf() : SimpleLeafBlueprint() {}
@@ -141,8 +141,8 @@ public:
// make public
using LeafBlueprint::set_want_global_filter;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
diff --git a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp
index d160b513534..542eb1bb4f8 100644
--- a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp
+++ b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp
@@ -74,8 +74,9 @@ struct DP {
FieldSpecList fields;
fields.add(FieldSpec(field, fieldId, handle, field_is_filter));
queryeval::Blueprint::UP bp = searchable.createBlueprint(requestContext, fields, *node);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP sb = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 10);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP sb = bp->createSearch(*md);
EXPECT_TRUE(dynamic_cast<DotProductSearch*>(sb.get()) != 0);
sb->initFullRange();
FakeResult result;
diff --git a/searchlib/src/tests/queryeval/equiv/equiv_test.cpp b/searchlib/src/tests/queryeval/equiv/equiv_test.cpp
index c570c06a60b..99045af7245 100644
--- a/searchlib/src/tests/queryeval/equiv/equiv_test.cpp
+++ b/searchlib/src/tests/queryeval/equiv/equiv_test.cpp
@@ -59,8 +59,9 @@ EquivTest::test_equiv(bool strict, bool unpack_normal_features, bool unpack_inte
data.setNeedNormalFeatures(unpack_normal_features);
data.setNeedInterleavedFeatures(unpack_interleaved_features);
}
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(3));
diff --git a/searchlib/src/tests/queryeval/fake_searchable/fake_searchable_test.cpp b/searchlib/src/tests/queryeval/fake_searchable/fake_searchable_test.cpp
index 8ddac327643..638ce30eb28 100644
--- a/searchlib/src/tests/queryeval/fake_searchable/fake_searchable_test.cpp
+++ b/searchlib/src/tests/queryeval/fake_searchable/fake_searchable_test.cpp
@@ -62,8 +62,9 @@ TEST_F(FakeSearchableTest, require_that_term_search_works) {
bool strict = (i == 0);
SCOPED_TRACE(strict ? "strict" : "non-strict");
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(3));
@@ -116,8 +117,9 @@ TEST_F(FakeSearchableTest, require_that_phrase_search_works) {
bool strict = (i == 0);
SCOPED_TRACE(strict ? "strict" : "non-strict");
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(3));
@@ -167,8 +169,9 @@ TEST_F(FakeSearchableTest, require_that_weigheted_set_search_works) {
bool strict = (i == 0);
SCOPED_TRACE(strict ? "strict" : "non-strict");
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(2));
@@ -238,8 +241,9 @@ TEST_F(FakeSearchableTest, require_that_multi_field_search_works) {
bool strict = (i == 0);
SCOPED_TRACE(strict ? "strict" : "non-strict");
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(3));
@@ -322,8 +326,9 @@ TEST_F(FakeSearchableTest, require_that_phrase_with_empty_child_works) {
bool strict = (i == 0);
SCOPED_TRACE(strict ? "strict" : "non-strict");
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(!search->seek(3));
@@ -342,8 +347,9 @@ TEST_F(FakeSearchableTest, require_that_match_data_is_compressed_for_attributes)
fields.add(FieldSpec("attrfoo", 1, 1));
Blueprint::UP bp = source.createBlueprint(req_ctx, fields, termNode);
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::FALSE);
- SearchIterator::UP search = bp->createSearch(*md, false);
+ bp->basic_plan(false, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
EXPECT_TRUE(search->seek(5));
search->unpack(5u);
@@ -369,8 +375,9 @@ TEST_F(FakeSearchableTest, require_that_relevant_data_can_be_obtained_from_fake_
fields.add(FieldSpec("attrfoo", 1, 1));
Blueprint::UP bp = source.createBlueprint(req_ctx, fields, termNode);
MatchData::UP md = MatchData::makeTestInstance(100, 10);
- bp->fetchPostings(ExecuteInfo::FALSE);
- SearchIterator::UP search = bp->createSearch(*md, false);
+ bp->basic_plan(false, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
EXPECT_TRUE(bp->get_attribute_search_context() != nullptr);
const auto *attr_ctx = bp->get_attribute_search_context();
ASSERT_TRUE(attr_ctx);
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 c4d34ab3565..5c29c293d82 100644
--- a/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp
+++ b/searchlib/src/tests/queryeval/filter_search/filter_search_test.cpp
@@ -36,8 +36,9 @@ constexpr auto upper_bound = Constraint::UPPER_BOUND;
const uint32_t docid_limit = 100;
template <typename T>
-concept FilterFactory = requires(const T &a, bool strict, Constraint constraint) {
- { a.createFilterSearch(strict, constraint) } -> std::same_as<std::unique_ptr<SearchIterator>>;
+concept FilterFactory = requires(const T &a, T &ma, InFlow in_flow, uint32_t my_docid_limit, bool strict, Constraint constraint) {
+ ma.basic_plan(in_flow, my_docid_limit);
+ { a.createFilterSearch(constraint) } -> std::same_as<std::unique_ptr<SearchIterator>>;
};
template <typename T>
@@ -45,20 +46,6 @@ concept ChildCollector = requires(T a, std::unique_ptr<Blueprint> bp) {
a.addChild(std::move(bp));
};
-// inherit Blueprint to capture the default filter factory
-struct DefaultBlueprint : Blueprint {
- FlowStats calculate_flow_stats(uint32_t) const override { abort(); }
- void optimize(Blueprint* &, OptimizePass) override { abort(); }
- double sort(InFlow, const Options &) override { abort(); }
- const State &getState() const override { abort(); }
- void fetchPostings(const ExecuteInfo &) override { abort(); }
- void freeze() override { abort(); }
- SearchIteratorUP createSearch(MatchData &, bool) const override { abort(); }
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
- }
-};
-
// proxy class used to make various decorators for leaf blueprints
// may be used directly to add the use of a field to a leaf blueprint
struct LeafProxy : SimpleLeafBlueprint {
@@ -71,10 +58,20 @@ struct LeafProxy : SimpleLeafBlueprint {
: SimpleLeafBlueprint(), child(std::move(child_in)) { init(); }
LeafProxy(FieldSpecBase field, std::unique_ptr<Blueprint> child_in)
: SimpleLeafBlueprint(field), child(std::move(child_in)) { init(); }
- FlowStats calculate_flow_stats(uint32_t) const override { abort(); }
- SearchIteratorUP createLeafSearch(const TermFieldMatchDataArray &, bool) const override { abort(); }
- SearchIteratorUP createFilterSearch(bool strict, Constraint constraint) const override {
- return child->createFilterSearch(strict, constraint);
+ void each_node_post_order(const std::function<void(Blueprint&)> &f) override {
+ child->each_node_post_order(f);
+ f(*this);
+ }
+ FlowStats calculate_flow_stats(uint32_t my_docid_limit) const override {
+ return child->calculate_flow_stats(my_docid_limit);
+ }
+ void sort(InFlow in_flow, const Options &opts) override {
+ strict(in_flow.strict());
+ child->sort(in_flow, opts);
+ }
+ SearchIteratorUP createLeafSearch(const TermFieldMatchDataArray &) const override { abort(); }
+ SearchIteratorUP createFilterSearch(Constraint constraint) const override {
+ return child->createFilterSearch(constraint);
}
};
@@ -82,15 +79,22 @@ struct LeafProxy : SimpleLeafBlueprint {
struct CheckParamsProxy : LeafProxy {
static bool current_strict; // <- changed by test
static Constraint current_constraint; // <- changed by test
+ bool expect_forced_strict = false;
bool expect_inherit_strict;
bool expect_same_constraint;
CheckParamsProxy(std::unique_ptr<Blueprint> child_in, bool expect_inherit_strict_in, bool expect_same_constraint_in)
: LeafProxy(std::move(child_in)),
expect_inherit_strict(expect_inherit_strict_in), expect_same_constraint(expect_same_constraint_in) {}
- SearchIteratorUP createFilterSearch(bool strict, Constraint constraint) const override {
- EXPECT_EQ(strict, (current_strict && expect_inherit_strict));
+ CheckParamsProxy(std::unique_ptr<Blueprint> child_in)
+ : LeafProxy(std::move(child_in)), expect_forced_strict(true), expect_inherit_strict(false), expect_same_constraint(true) {}
+ SearchIteratorUP createFilterSearch(Constraint constraint) const override {
+ if (expect_forced_strict) {
+ EXPECT_EQ(strict(), true);
+ } else {
+ EXPECT_EQ(strict(), (current_strict && expect_inherit_strict));
+ }
EXPECT_EQ((constraint == current_constraint), expect_same_constraint);
- return child->createFilterSearch(strict, constraint);
+ return child->createFilterSearch(constraint);
}
};
bool CheckParamsProxy::current_strict = false;
@@ -101,9 +105,9 @@ struct CheckDroppedProxy : LeafProxy {
mutable bool used;
CheckDroppedProxy(std::unique_ptr<Blueprint> child_in)
: LeafProxy(std::move(child_in)), used(false) {}
- SearchIteratorUP createFilterSearch(bool strict, Constraint constraint) const override {
+ SearchIteratorUP createFilterSearch(Constraint constraint) const override {
used = true;
- return child->createFilterSearch(strict, constraint);
+ return child->createFilterSearch(constraint);
}
~CheckDroppedProxy() override {
EXPECT_EQ(used, false);
@@ -162,6 +166,10 @@ std::unique_ptr<Blueprint> check(std::unique_ptr<Blueprint> child, bool expect_i
return std::make_unique<CheckParamsProxy>(std::move(child), expect_inherit_strict, expect_same_constraint);
}
+std::unique_ptr<Blueprint> check_forced(std::unique_ptr<Blueprint> child) {
+ return std::make_unique<CheckParamsProxy>(std::move(child));
+}
+
// check that create filter is not called
std::unique_ptr<Blueprint> dropped(std::unique_ptr<Blueprint> child) {
return std::make_unique<CheckDroppedProxy>(std::move(child));
@@ -191,6 +199,11 @@ struct Children {
list.back() = [=](){ return ::check(old_factory(), expect_inherit_strict, expect_same_constraint); };
return *this;
}
+ Children &check_forced() {
+ Factory old_factory = list.back();
+ list.back() = [=](){ return ::check_forced(old_factory()); };
+ return *this;
+ }
Children &dropped() {
Factory old_factory = list.back();
list.back() = [=](){ return ::dropped(old_factory()); };
@@ -204,29 +217,44 @@ struct Children {
}
};
+struct NoFlow {
+ NoFlow(InFlow) noexcept {}
+ void add(double) noexcept {};
+ bool strict() noexcept { return false; }
+ double flow() noexcept { return 0.0; }
+};
+
// Combine children blueprints using a shared filter creation
// algorithm. Satisfies the FilterFactory concept.
+template <typename Flow>
struct Combine {
using factory_fun = std::function<std::unique_ptr<SearchIterator>(const Blueprint::Children &, bool, Constraint)>;
factory_fun fun;
+ bool strict;
Blueprint::Children list;
- Combine(factory_fun fun_in, const Children &child_list);
+ Combine(factory_fun fun_in, const Children &child_list)
+ : fun(fun_in), strict(false), list()
+ {
+ child_list.apply(*this);
+ }
~Combine();
void addChild(std::unique_ptr<Blueprint> child) {
list.push_back(std::move(child));
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ strict = in_flow.strict();
+ Flow flow(in_flow);
+ for (auto &child: list) {
+ child->basic_plan(InFlow(flow.strict(), flow.flow()), my_docid_limit);
+ flow.add(child->estimate());
+ }
+ }
+ auto createFilterSearch(Constraint constraint) const {
return fun(list, strict, constraint);
}
};
-
-Combine::Combine(factory_fun fun_in, const Children &child_list)
- : fun(fun_in), list()
-{
- child_list.apply(*this);
-}
-
-Combine::~Combine() = default;
+template <typename Flow>
+Combine<Flow>::~Combine() = default;
// enable Make-ing source blender
struct SourceBlenderAdapter {
@@ -236,8 +264,11 @@ struct SourceBlenderAdapter {
void addChild(std::unique_ptr<Blueprint> child) {
blueprint.addChild(std::move(child));
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -251,8 +282,11 @@ struct SimplePhraseAdapter {
auto term = std::make_unique<LeafProxy>(child_field, std::move(child));
blueprint.addTerm(std::move(term));
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -264,8 +298,11 @@ struct EquivAdapter {
void addChild(std::unique_ptr<Blueprint> child) {
blueprint.addTerm(std::move(child), 1.0);
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -280,8 +317,11 @@ struct WeightedSetTermAdapter {
blueprint.addTerm(std::move(child), 100, estimate);
blueprint.complete(estimate);
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -301,8 +341,11 @@ struct DotProductAdapter {
blueprint.addTerm(std::move(term), 100, estimate);
blueprint.complete(estimate);
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -321,8 +364,11 @@ struct ParallelWeakAndAdapter {
blueprint.addTerm(std::move(term), 100, estimate);
blueprint.complete(estimate);
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -337,8 +383,11 @@ struct SameElementAdapter {
auto term = std::make_unique<LeafProxy>(child_field, std::move(child));
blueprint.addTerm(std::move(term));
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -355,8 +404,11 @@ struct Make {
Make(const Children &child_list, Args && ... args) : blueprint(std::forward<Args>(args)...) {
child_list.apply(blueprint);
}
- auto createFilterSearch(bool strict, Constraint constraint) const {
- return blueprint.createFilterSearch(strict, constraint);
+ void basic_plan(InFlow in_flow, uint32_t my_docid_limit) {
+ blueprint.basic_plan(in_flow, my_docid_limit);
+ }
+ auto createFilterSearch(Constraint constraint) const {
+ return blueprint.createFilterSearch(constraint);
}
};
@@ -381,10 +433,11 @@ struct Expect {
};
template <FilterFactory Blueprint>
-void verify(const Blueprint &blueprint, bool strict, Constraint constraint, const Expect &expect) {
+void verify(Blueprint &&blueprint, bool strict, Constraint constraint, const Expect &expect) {
CheckParamsProxy::current_strict = strict;
CheckParamsProxy::current_constraint = constraint;
- auto filter = blueprint.createFilterSearch(strict, constraint);
+ blueprint.basic_plan(strict, docid_limit);
+ auto filter = blueprint.createFilterSearch(constraint);
if (expect.children > 0) {
ASSERT_EQ(filter->isMultiSearch(), true);
EXPECT_EQ(static_cast<MultiSearch*>(filter.get())->getChildren().size(), expect.children);
@@ -409,14 +462,14 @@ void verify(const Blueprint &blueprint, bool strict, Constraint constraint, cons
}
template <FilterFactory Blueprint>
-void verify(const Blueprint &blueprint, bool strict, const Expect &expect) {
+void verify(Blueprint &&blueprint, bool strict, const Expect &expect) {
for (auto constraint: {lower_bound, upper_bound}) {
verify(blueprint, strict, constraint, expect);
}
}
template <FilterFactory Blueprint>
-void verify(const Blueprint &blueprint, const Expect &upper, const Expect &lower) {
+void verify(Blueprint &&blueprint, const Expect &upper, const Expect &lower) {
for (auto constraint: {lower_bound, upper_bound}) {
const Expect &expect = (constraint == upper_bound) ? upper : lower;
for (bool strict: {false, true}) {
@@ -426,7 +479,7 @@ void verify(const Blueprint &blueprint, const Expect &upper, const Expect &lower
}
template <FilterFactory Blueprint>
-void verify(const Blueprint &blueprint, const Expect &upper_and_lower) {
+void verify(Blueprint &&blueprint, const Expect &upper_and_lower) {
verify(blueprint, upper_and_lower, upper_and_lower);
}
@@ -443,12 +496,12 @@ TEST(FilterSearchTest, custom_leaf) {
}
TEST(FilterSearchTest, default_filter) {
- verify(DefaultBlueprint(), Expect::full(), Expect::empty());
- auto adapter = [](const auto &ignore_children, bool strict, Constraint constraint) {
+ auto adapter = [](const auto &ignore_children, bool ignore_strict, Constraint constraint) {
(void) ignore_children;
- return Blueprint::create_default_filter(strict, constraint);
+ (void) ignore_strict;
+ return Blueprint::create_default_filter(constraint);
};
- verify(Combine(adapter, Children()), Expect::full(), Expect::empty());
+ verify(Combine<NoFlow>(adapter, Children()), Expect::full(), Expect::empty());
}
TEST(FilterSearchTest, simple_or) {
@@ -457,39 +510,55 @@ TEST(FilterSearchTest, simple_or) {
.hits({7}).check(true, true)
.hits({3, 11}).check(true, true);
auto expected = Expect::hits({3, 5, 7, 10, 11});
- verify(Combine(Blueprint::create_or_filter, child_list), expected);
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, child_list), expected);
verify(Make<OrBlueprint>(child_list), expected);
verify(Make<EquivAdapter>(child_list), expected);
- verify(Make<WeightedSetTermAdapter>(child_list), expected);
- verify(Make<DotProductAdapter>(child_list), expected);
- verify(Combine(Blueprint::create_atmost_or_filter, child_list), expected, Expect::empty());
+ verify(Combine<OrFlow>(Blueprint::create_atmost_or_filter, child_list), expected, Expect::empty());
verify(Make<WeakAndBlueprint>(child_list, 100), expected, Expect::empty());
verify(Make<SourceBlenderAdapter>(child_list), expected, Expect::empty());
verify(Make<ParallelWeakAndAdapter>(child_list), expected, Expect::empty());
}
+TEST(FilterSearchTest, forced_or) {
+ auto child_list = Children()
+ .hits({5, 10}).check_forced()
+ .hits({7}).check_forced()
+ .hits({3, 11}).check_forced();
+ auto expected = Expect::hits({3, 5, 7, 10, 11});
+ verify(Make<WeightedSetTermAdapter>(child_list), expected);
+ verify(Make<DotProductAdapter>(child_list), expected);
+}
+
TEST(FilterSearchTest, simple_and) {
auto child_list = Children()
- .hits({1, 2, 3, 4, 5, 6}).check(true, true)
- .hits({2, 4, 6, 7}).check(false, true)
- .hits({1, 4, 6, 7, 10}).check(false, true);
+ .hits({2, 4, 6, 7}).check(true, true)
+ .hits({1, 4, 6, 7, 10}).check(false, true)
+ .hits({1, 2, 3, 4, 5, 6}).check(false, true);
auto expected = Expect::hits({4, 6});
- verify(Combine(Blueprint::create_and_filter, child_list), expected);
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list), expected);
verify(Make<AndBlueprint>(child_list), expected);
- verify(Combine(Blueprint::create_atmost_and_filter, child_list), expected, Expect::empty());
+ verify(Combine<AndFlow>(Blueprint::create_atmost_and_filter, child_list), expected, Expect::empty());
verify(Make<NearBlueprint>(child_list, 3), expected, Expect::empty());
verify(Make<ONearBlueprint>(child_list, 3), expected, Expect::empty());
- verify(Make<SimplePhraseAdapter>(child_list), expected, Expect::empty());
verify(Make<SameElementAdapter>(child_list), expected, Expect::empty());
}
+TEST(FilterSearchTest, eager_and) {
+ auto child_list = Children()
+ .hits({2, 4, 6, 7}).check(true, true)
+ .hits({1, 4, 6, 7, 10}).check(true, true)
+ .hits({1, 2, 3, 4, 5, 6}).check(true, true);
+ auto expected = Expect::hits({4, 6});
+ verify(Make<SimplePhraseAdapter>(child_list), expected, Expect::empty());
+}
+
TEST(FilterSearchTest, simple_andnot) {
auto child_list = Children()
.hits({1, 2, 3, 4, 5, 6}).check(true, true)
.hits({2, 4, 6}).check(false, false)
.hits({4, 6, 7}).check(false, false);
auto expected = Expect::hits({1, 3, 5});
- verify(Combine(Blueprint::create_andnot_filter, child_list), expected);
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list), expected);
verify(Make<AndNotBlueprint>(child_list), expected);
}
@@ -497,9 +566,13 @@ TEST(FilterSearchTest, rank_filter) {
auto child_list1 = Children().hits({1,2,3}).empty().full();
auto child_list2 = Children().empty().hits({1,2,3}).full();
auto child_list3 = Children().full().hits({1,2,3}).empty();
- verify(Combine(Blueprint::create_first_child_filter, child_list1), Expect::hits({1,2,3}));
- verify(Combine(Blueprint::create_first_child_filter, child_list2), Expect::empty());
- verify(Combine(Blueprint::create_first_child_filter, child_list3), Expect::full());
+ auto adapter = [](const auto &children, bool ignore_strict, Constraint constraint) {
+ (void) ignore_strict;
+ return Blueprint::create_first_child_filter(children, constraint);
+ };
+ verify(Combine<RankFlow>(adapter, child_list1), Expect::hits({1,2,3}));
+ verify(Combine<RankFlow>(adapter, child_list2), Expect::empty());
+ verify(Combine<RankFlow>(adapter, child_list3), Expect::full());
verify(Make<RankBlueprint>(child_list1), Expect::hits({1,2,3}));
verify(Make<RankBlueprint>(child_list2), Expect::empty());
verify(Make<RankBlueprint>(child_list3), Expect::full());
@@ -510,7 +583,7 @@ TEST(FilterSearchTest, or_short_circuit) {
.hits({5, 10}).check(true, true)
.full().check(true, true)
.hits({3, 11}).check(true, true).dropped();
- verify(Combine(Blueprint::create_or_filter, child_list),
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, child_list),
Expect::full());
}
@@ -519,7 +592,7 @@ TEST(FilterSearchTest, or_pruning) {
.empty().check(true, true)
.empty().check(true, true)
.empty().check(true, true);
- verify(Combine(Blueprint::create_or_filter, child_list),
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, child_list),
Expect::empty());
}
@@ -528,7 +601,7 @@ TEST(FilterSearchTest, or_partial_pruning) {
.hits({5, 10}).check(true, true)
.empty().check(true, true)
.hits({3, 11}).check(true, true);
- verify(Combine(Blueprint::create_or_filter, child_list),
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, child_list),
Expect::hits({3, 5, 10, 11}).child_count(2));
}
@@ -537,7 +610,7 @@ TEST(FilterSearchTest, and_short_circuit) {
.hits({1, 2, 3}).check(true, true)
.empty().check(false, true)
.hits({2, 3, 4}).check(false, true).dropped();
- verify(Combine(Blueprint::create_and_filter, child_list),
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list),
Expect::empty());
}
@@ -546,7 +619,7 @@ TEST(FilterSearchTest, and_pruning) {
.full().check(true, true)
.full().check(false, true)
.full().check(false, true);
- verify(Combine(Blueprint::create_and_filter, child_list),
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list),
Expect::full());
}
@@ -555,7 +628,7 @@ TEST(FilterSearchTest, and_partial_pruning) {
.hits({1, 2, 3}).check(true, true)
.full().check(false, true)
.hits({2, 3, 4}).check(false, true);
- verify(Combine(Blueprint::create_and_filter, child_list),
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list),
Expect::hits({2, 3}).child_count(2));
}
@@ -563,7 +636,7 @@ TEST(FilterSearchTest, andnot_positive_short_circuit) {
auto child_list = Children()
.empty().check(true, true)
.hits({1, 2, 3}).check(false, false).dropped();
- verify(Combine(Blueprint::create_andnot_filter, child_list),
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list),
Expect::empty());
}
@@ -573,7 +646,7 @@ TEST(FilterSearchTest, andnot_negative_short_circuit) {
.hits({1}).check(false, false)
.full().check(false, false)
.hits({3}).check(false, false).dropped();
- verify(Combine(Blueprint::create_andnot_filter, child_list),
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list),
Expect::empty());
}
@@ -583,7 +656,7 @@ TEST(FilterSearchTest, andnot_negative_pruning) {
.empty().check(false, false)
.empty().check(false, false)
.empty().check(false, false);
- verify(Combine(Blueprint::create_andnot_filter, child_list),
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list),
Expect::full());
}
@@ -593,7 +666,7 @@ TEST(FilterSearchTest, andnot_partial_negative_pruning) {
.hits({1}).check(false, false)
.empty().check(false, false)
.hits({3}).check(false, false);
- verify(Combine(Blueprint::create_andnot_filter, child_list),
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list),
Expect::hits({2}).child_count(3));
}
@@ -602,7 +675,7 @@ TEST(FilterSearchTest, first_or_child_can_be_partially_pruned) {
.empty().check(true, true)
.hits({5, 10}).check(true, true)
.hits({3, 11}).check(true, true);
- verify(Combine(Blueprint::create_or_filter, child_list),
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, child_list),
Expect::hits({3, 5, 10, 11}).child_count(2));
}
@@ -611,9 +684,9 @@ TEST(FilterSearchTest, first_and_child_can_only_be_partially_pruned_when_nonstri
.full().check(true, true)
.hits({1, 2, 3}).check(false, true)
.hits({2, 3, 4}).check(false, true);
- verify(Combine(Blueprint::create_and_filter, child_list), true,
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list), true,
Expect::hits({2, 3}).child_count(3));
- verify(Combine(Blueprint::create_and_filter, child_list), false,
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, child_list), false,
Expect::hits({2, 3}).child_count(2));
}
@@ -623,19 +696,19 @@ TEST(FilterSearchTest, first_negative_andnot_child_can_be_partially_pruned) {
.empty().check(false, false)
.hits({1}).check(false, false)
.hits({3}).check(false, false);
- verify(Combine(Blueprint::create_andnot_filter, child_list),
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, child_list),
Expect::hits({2}).child_count(3));
}
TEST(FilterSearchTest, need_atleast_one_child) {
- verify(Combine(Blueprint::create_and_filter, Children().full()), Expect::full());
- verify(Combine(Blueprint::create_or_filter, Children().empty()), Expect::empty());
- verify(Combine(Blueprint::create_andnot_filter, Children().full()), Expect::full());
- EXPECT_THROW(verify(Combine(Blueprint::create_and_filter, Children()), Expect::empty()),
+ verify(Combine<AndFlow>(Blueprint::create_and_filter, Children().full()), Expect::full());
+ verify(Combine<OrFlow>(Blueprint::create_or_filter, Children().empty()), Expect::empty());
+ verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, Children().full()), Expect::full());
+ EXPECT_THROW(verify(Combine<AndFlow>(Blueprint::create_and_filter, Children()), Expect::empty()),
vespalib::RequireFailedException);
- EXPECT_THROW(verify(Combine(Blueprint::create_or_filter, Children()), Expect::empty()),
+ EXPECT_THROW(verify(Combine<OrFlow>(Blueprint::create_or_filter, Children()), Expect::empty()),
vespalib::RequireFailedException);
- EXPECT_THROW(verify(Combine(Blueprint::create_andnot_filter, Children()), Expect::empty()),
+ EXPECT_THROW(verify(Combine<AndNotFlow>(Blueprint::create_andnot_filter, Children()), Expect::empty()),
vespalib::RequireFailedException);
}
diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp
index 202ba8c180e..33c2e067255 100644
--- a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp
+++ b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp
@@ -156,7 +156,7 @@ get_class_name(const auto& obj)
BenchmarkResult
strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit)
{
- auto itr = blueprint.createSearch(md, true);
+ auto itr = blueprint.createSearch(md);
assert(itr.get());
BenchmarkTimer timer(budget_sec);
uint32_t hits = 0;
@@ -176,9 +176,9 @@ strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit)
}
BenchmarkResult
-non_strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit, double filter_hit_ratio, bool force_strict)
+non_strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit, double filter_hit_ratio)
{
- auto itr = blueprint.createSearch(md, force_strict);
+ auto itr = blueprint.createSearch(md);
assert(itr.get());
BenchmarkTimer timer(budget_sec);
uint32_t seeks = 0;
@@ -209,16 +209,15 @@ non_strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit, dou
BenchmarkResult
benchmark_search(Blueprint::UP blueprint, uint32_t docid_limit, bool strict_context, bool force_strict, double filter_hit_ratio)
{
- auto opts = Blueprint::Options::all();
- blueprint->sort(strict_context || force_strict, opts);
- blueprint->fetchPostings(ExecuteInfo::createForTest(strict_context || force_strict));
+ blueprint->basic_plan(strict_context || force_strict, docid_limit);
+ blueprint->fetchPostings(ExecuteInfo::FULL);
// Note: All blueprints get the same TermFieldMatchData instance.
// This is OK as long as we don't do unpacking and only use 1 thread.
auto md = MatchData::makeTestInstance(1, 1);
if (strict_context) {
return strict_search(*blueprint, *md, docid_limit);
} else {
- return non_strict_search(*blueprint, *md, docid_limit, filter_hit_ratio, force_strict);
+ return non_strict_search(*blueprint, *md, docid_limit, filter_hit_ratio);
}
}
diff --git a/searchlib/src/tests/queryeval/parallel_weak_and/parallel_weak_and_test.cpp b/searchlib/src/tests/queryeval/parallel_weak_and/parallel_weak_and_test.cpp
index 7a7abb20cdf..992ac320385 100644
--- a/searchlib/src/tests/queryeval/parallel_weak_and/parallel_weak_and_test.cpp
+++ b/searchlib/src/tests/queryeval/parallel_weak_and/parallel_weak_and_test.cpp
@@ -179,9 +179,9 @@ struct WandBlueprintSpec
Node::UP term = createNode();
Blueprint::UP bp = blueprint(searchable, field, *term);
MatchData::UP md(MatchData::makeTestInstance(1, 1));
- bp->fetchPostings(ExecuteInfo::TRUE);
- bp->setDocIdLimit(docIdLimit);
- SearchIterator::UP sb = bp->createSearch(*md, true);
+ bp->basic_plan(true, docIdLimit);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP sb = bp->createSearch(*md);
EXPECT_TRUE(dynamic_cast<ParallelWeakAndSearch*>(sb.get()) != 0);
return sb;
}
@@ -194,9 +194,9 @@ struct WandBlueprintSpec
FakeResult search(Searchable &searchable, const std::string &field, const search::query::Node &term) const {
Blueprint::UP bp = blueprint(searchable, field, term);
MatchData::UP md(MatchData::makeTestInstance(1, 1));
- bp->fetchPostings(ExecuteInfo::TRUE);
- bp->setDocIdLimit(docIdLimit);
- SearchIterator::UP sb = bp->createSearch(*md, true);
+ bp->basic_plan(true, docIdLimit);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP sb = bp->createSearch(*md);
EXPECT_TRUE(dynamic_cast<ParallelWeakAndSearch*>(sb.get()) != 0);
return doSearch(*sb, *md->resolveTermField(handle));
}
diff --git a/searchlib/src/tests/queryeval/predicate/predicate_blueprint_test.cpp b/searchlib/src/tests/queryeval/predicate/predicate_blueprint_test.cpp
index ed349480ff4..ffa2905ce0e 100644
--- a/searchlib/src/tests/queryeval/predicate/predicate_blueprint_test.cpp
+++ b/searchlib/src/tests/queryeval/predicate/predicate_blueprint_test.cpp
@@ -128,13 +128,14 @@ TEST_F("require that blueprint with zstar-compressed estimates non-empty.", Fixt
void
runQuery(Fixture & f, std::vector<uint32_t> expected, bool expectCachedSize, uint32_t expectedKV) {
PredicateBlueprint blueprint(f.field, f.guard(), f.query);
- blueprint.fetchPostings(ExecuteInfo::TRUE);
+ blueprint.basic_plan(true, 100);
+ blueprint.fetchPostings(ExecuteInfo::FULL);
EXPECT_EQUAL(expectCachedSize, blueprint.getCachedFeatures().size());
for (uint32_t docId : expected) {
EXPECT_EQUAL(expectedKV, uint32_t(blueprint.getKV()[docId]));
}
TermFieldMatchDataArray tfmda;
- SearchIterator::UP it = blueprint.createLeafSearch(tfmda, true);
+ SearchIterator::UP it = blueprint.createLeafSearch(tfmda);
ASSERT_TRUE(it.get());
it->initFullRange();
EXPECT_EQUAL(SearchIterator::beginId(), it->getDocId());
@@ -172,9 +173,10 @@ TEST_F("require that blueprint can create more advanced search", Fixture) {
f.indexEmptyDocument(doc_id + 2);
PredicateBlueprint blueprint(f.field, f.guard(), f.query);
- blueprint.fetchPostings(ExecuteInfo::TRUE);
+ blueprint.basic_plan(true, 100);
+ blueprint.fetchPostings(ExecuteInfo::FULL);
TermFieldMatchDataArray tfmda;
- SearchIterator::UP it = blueprint.createLeafSearch(tfmda, true);
+ SearchIterator::UP it = blueprint.createLeafSearch(tfmda);
ASSERT_TRUE(it.get());
it->initFullRange();
EXPECT_EQUAL(SearchIterator::beginId(), it->getDocId());
@@ -195,9 +197,10 @@ TEST_F("require that blueprint can create NOT search", Fixture) {
f.indexDocument(doc_id, annotations);
PredicateBlueprint blueprint(f.field, f.guard(), f.query);
- blueprint.fetchPostings(ExecuteInfo::TRUE);
+ blueprint.basic_plan(true, 100);
+ blueprint.fetchPostings(ExecuteInfo::FULL);
TermFieldMatchDataArray tfmda;
- SearchIterator::UP it = blueprint.createLeafSearch(tfmda, true);
+ SearchIterator::UP it = blueprint.createLeafSearch(tfmda);
ASSERT_TRUE(it.get());
it->initFullRange();
EXPECT_TRUE(it->seek(doc_id));
@@ -211,9 +214,10 @@ TEST_F("require that blueprint can create compressed NOT search", Fixture) {
f.indexDocument(doc_id, annotations);
PredicateBlueprint blueprint(f.field, f.guard(), f.query);
- blueprint.fetchPostings(ExecuteInfo::TRUE);
+ blueprint.basic_plan(true, 100);
+ blueprint.fetchPostings(ExecuteInfo::FULL);
TermFieldMatchDataArray tfmda;
- SearchIterator::UP it = blueprint.createLeafSearch(tfmda, true);
+ SearchIterator::UP it = blueprint.createLeafSearch(tfmda);
ASSERT_TRUE(it.get());
it->initFullRange();
EXPECT_TRUE(it->seek(doc_id));
@@ -235,9 +239,10 @@ TEST_F("require that blueprint can set up search with subqueries", Fixture) {
query.getTerm()->addFeature("key2", "value", 2);
PredicateBlueprint blueprint(f.field, f.guard(), query);
- blueprint.fetchPostings(ExecuteInfo::TRUE);
+ blueprint.basic_plan(true, 100);
+ blueprint.fetchPostings(ExecuteInfo::FULL);
TermFieldMatchDataArray tfmda;
- SearchIterator::UP it = blueprint.createLeafSearch(tfmda, true);
+ SearchIterator::UP it = blueprint.createLeafSearch(tfmda);
ASSERT_TRUE(it.get());
it->initFullRange();
EXPECT_FALSE(it->seek(doc_id));
diff --git a/searchlib/src/tests/queryeval/queryeval_test.cpp b/searchlib/src/tests/queryeval/queryeval_test.cpp
index e8f30ba84ff..b72481d24cf 100644
--- a/searchlib/src/tests/queryeval/queryeval_test.cpp
+++ b/searchlib/src/tests/queryeval/queryeval_test.cpp
@@ -220,8 +220,9 @@ TEST(QueryEvalTest, test_and) {
auto and_b = std::make_unique<AndBlueprint>();
and_b->addChild(std::make_unique<SimpleBlueprint>(a));
and_b->addChild(std::make_unique<SimpleBlueprint>(b));
- and_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP and_ab = and_b->createSearch(*md, true);
+ and_b->basic_plan(true, 1000);
+ and_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP and_ab = and_b->createSearch(*md);
EXPECT_TRUE(dynamic_cast<const AndSearch *>(and_ab.get()) != nullptr);
EXPECT_EQ(4u, dynamic_cast<AndSearch &>(*and_ab).estimate());
@@ -231,14 +232,16 @@ TEST(QueryEvalTest, test_and) {
expect.addHit(5).addHit(30);
EXPECT_EQ(res, expect);
- SearchIterator::UP filter_ab = and_b->createFilterSearch(true, upper_bound);
+ SearchIterator::UP filter_ab = and_b->createFilterSearch(upper_bound);
SimpleResult filter_res;
filter_res.search(*filter_ab);
EXPECT_EQ(res, expect);
std::string dump = filter_ab->asString();
expect_match(dump, "upper");
expect_match(dump, "AndSearchStrict.*NoUnpack.*SimpleSearch.*upper.*SimpleSearch.*upper");
- filter_ab = and_b->createFilterSearch(false, lower_bound);
+ and_b->basic_plan(false, 1000);
+ and_b->fetchPostings(ExecuteInfo::FULL);
+ filter_ab = and_b->createFilterSearch(lower_bound);
dump = filter_ab->asString();
expect_match(dump, "lower");
expect_match(dump, "AndSearchNoStrict.*NoUnpack.*SimpleSearch.*lower.*SimpleSearch.*lower");
@@ -256,8 +259,9 @@ TEST(QueryEvalTest, test_or)
auto or_b = std::make_unique<OrBlueprint>();
or_b->addChild(std::make_unique<SimpleBlueprint>(a));
or_b->addChild(std::make_unique<SimpleBlueprint>(b));
- or_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP or_ab = or_b->createSearch(*md, true);
+ or_b->basic_plan(true, 1000);
+ or_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP or_ab = or_b->createSearch(*md);
SimpleResult res;
res.search(*or_ab);
@@ -265,14 +269,16 @@ TEST(QueryEvalTest, test_or)
expect.addHit(5).addHit(10).addHit(17).addHit(30);
EXPECT_EQ(res, expect);
- SearchIterator::UP filter_ab = or_b->createFilterSearch(true, upper_bound);
+ SearchIterator::UP filter_ab = or_b->createFilterSearch(upper_bound);
SimpleResult filter_res;
filter_res.search(*filter_ab);
EXPECT_EQ(res, expect);
std::string dump = filter_ab->asString();
expect_match(dump, "upper");
expect_match(dump, "StrictHeapOrSearch.*NoUnpack.*SimpleSearch.*upper.*SimpleSearch.*upper");
- filter_ab = or_b->createFilterSearch(false, lower_bound);
+ or_b->basic_plan(false, 1000);
+ or_b->fetchPostings(ExecuteInfo::FULL);
+ filter_ab = or_b->createFilterSearch(lower_bound);
dump = filter_ab->asString();
expect_match(dump, "lower");
expect_match(dump, "OrLikeSearch.false.*NoUnpack.*SimpleSearch.*lower.*SimpleSearch.*lower");
@@ -365,13 +371,13 @@ public:
: default_flow_stats(docid_limit, est.est_hits(), 0);
}
SearchIterator::UP
- createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override
+ createLeafSearch(const TermFieldMatchDataArray &tfmda) const override
{
(void) tfmda;
- return _sc->createIterator(&_tfmd, strict);
+ return _sc->createIterator(&_tfmd, strict());
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
private:
search::SingleBoolAttribute _a;
@@ -392,8 +398,9 @@ TEST(QueryEvalTest, test_andnot)
auto andnot_b = std::make_unique<AndNotBlueprint>();
andnot_b->addChild(std::make_unique<SimpleBlueprint>(a));
andnot_b->addChild(std::make_unique<SimpleBlueprint>(b));
- andnot_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP andnot_ab = andnot_b->createSearch(*md, true);
+ andnot_b->basic_plan(true, 1000);
+ andnot_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP andnot_ab = andnot_b->createSearch(*md);
SimpleResult res;
res.search(*andnot_ab);
@@ -401,14 +408,16 @@ TEST(QueryEvalTest, test_andnot)
expect.addHit(10);
EXPECT_EQ(res, expect);
- SearchIterator::UP filter_ab = andnot_b->createFilterSearch(true, upper_bound);
+ SearchIterator::UP filter_ab = andnot_b->createFilterSearch(upper_bound);
SimpleResult filter_res;
filter_res.search(*filter_ab);
EXPECT_EQ(res, expect);
std::string dump = filter_ab->asString();
expect_match(dump, "upper");
expect_match(dump, "AndNotSearch.*SimpleSearch.*<strict,upper>.*SimpleSearch.*<nostrict,lower>");
- filter_ab = andnot_b->createFilterSearch(false, lower_bound);
+ andnot_b->basic_plan(false, 1000);
+ andnot_b->fetchPostings(ExecuteInfo::FULL);
+ filter_ab = andnot_b->createFilterSearch(lower_bound);
dump = filter_ab->asString();
expect_match(dump, "lower");
expect_match(dump, "AndNotSearch.*SimpleSearch.*<nostrict,lower>.*SimpleSearch.*<nostrict,upper>");
@@ -423,8 +432,9 @@ TEST(QueryEvalTest, test_andnot)
auto andnot_b = std::make_unique<AndNotBlueprint>();
andnot_b->addChild(std::make_unique<SimpleBlueprint>(a));
andnot_b->addChild(std::make_unique<DummySingleValueBitNumericAttributeBlueprint>(b));
- andnot_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP andnot_ab = andnot_b->createSearch(*md, true);
+ andnot_b->basic_plan(true, 1000);
+ andnot_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP andnot_ab = andnot_b->createSearch(*md);
SimpleResult res;
res.search(*andnot_ab);
@@ -449,8 +459,9 @@ TEST(QueryEvalTest, test_andnot)
auto and_b = std::make_unique<AndBlueprint>();
and_b->addChild(std::make_unique<SimpleBlueprint>(c));
and_b->addChild(std::move(andnot_b));
- and_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP and_cab = and_b->createSearch(*md, true);
+ and_b->basic_plan(true, 1000);
+ and_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP and_cab = and_b->createSearch(*md);
SimpleResult res;
res.search(*and_cab);
@@ -475,8 +486,9 @@ TEST(QueryEvalTest, test_rank)
auto rank_b = std::make_unique<RankBlueprint>();
rank_b->addChild(std::make_unique<SimpleBlueprint>(a));
rank_b->addChild(std::make_unique<SimpleBlueprint>(b));
- rank_b->fetchPostings(ExecuteInfo::TRUE);
- SearchIterator::UP rank_ab = rank_b->createSearch(*md, true);
+ rank_b->basic_plan(true, 1000);
+ rank_b->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP rank_ab = rank_b->createSearch(*md);
SimpleResult res;
res.search(*rank_ab);
diff --git a/searchlib/src/tests/queryeval/same_element/same_element_test.cpp b/searchlib/src/tests/queryeval/same_element/same_element_test.cpp
index 64f4fafd2d1..9d93ade71d9 100644
--- a/searchlib/src/tests/queryeval/same_element/same_element_test.cpp
+++ b/searchlib/src/tests/queryeval/same_element/same_element_test.cpp
@@ -46,9 +46,8 @@ std::unique_ptr<SameElementBlueprint> make_blueprint(const std::vector<FakeResul
}
Blueprint::UP finalize(Blueprint::UP bp, bool strict) {
- auto opts = Blueprint::Options::all();
- Blueprint::UP result = Blueprint::optimize_and_sort(std::move(bp), true, opts);
- result->fetchPostings(ExecuteInfo::createForTest(strict));
+ Blueprint::UP result = Blueprint::optimize_and_sort(std::move(bp), strict);
+ result->fetchPostings(ExecuteInfo::FULL);
result->freeze();
return result;
}
@@ -56,7 +55,7 @@ Blueprint::UP finalize(Blueprint::UP bp, bool strict) {
SimpleResult find_matches(const std::vector<FakeResult> &children) {
auto md = make_match_data();
auto bp = finalize(make_blueprint(children), false);
- auto search = bp->createSearch(*md, false);
+ auto search = bp->createSearch(*md);
return SimpleResult().search(*search, 1000);
}
@@ -85,7 +84,7 @@ TEST("require that matching elements can be identified") {
auto b = make_result({{5, {3,5,7,10}}, {10, {4,5,6}}});
auto bp = finalize(make_blueprint({a,b}), false);
auto md = make_match_data();
- auto search = bp->createSearch(*md, false);
+ auto search = bp->createSearch(*md);
search->initRange(1, 1000);
auto *se = dynamic_cast<SameElementSearch*>(search.get());
ASSERT_TRUE(se != nullptr);
@@ -107,7 +106,7 @@ TEST("require that strict iterator seeks to next hit and can unpack matching doc
auto a = make_result({{5, {1,2}}, {7, {1,2}}, {8, {1,2}}, {9, {1,2}}});
auto b = make_result({{5, {3}}, {6, {1,2}}, {7, {2,4}}, {9, {1}}});
auto bp = finalize(make_blueprint({a,b}), true);
- auto search = bp->createSearch(*md, true);
+ auto search = bp->createSearch(*md);
auto* tfmd = md->resolveTermField(0);
search->initRange(1, 1000);
EXPECT_LESS(search->getDocId(), 1u);
@@ -145,9 +144,9 @@ TEST("require that children are sorted") {
TEST("require that attribute iterators are wrapped for element unpacking") {
auto a = make_result({{5, {1,3,7}}});
auto b = make_result({{5, {3,5,10}}});
- auto bp = finalize(make_blueprint({a,b}, true), true);
+ auto bp = finalize(make_blueprint({a,b}, true), false);
auto md = make_match_data();
- auto search = bp->createSearch(*md, false);
+ auto search = bp->createSearch(*md);
auto *se = dynamic_cast<SameElementSearch*>(search.get());
ASSERT_TRUE(se != nullptr);
ASSERT_EQUAL(se->children().size(), 2u);
diff --git a/searchlib/src/tests/queryeval/simple_phrase/simple_phrase_test.cpp b/searchlib/src/tests/queryeval/simple_phrase/simple_phrase_test.cpp
index 99812900d40..3e779bdca14 100644
--- a/searchlib/src/tests/queryeval/simple_phrase/simple_phrase_test.cpp
+++ b/searchlib/src/tests/queryeval/simple_phrase/simple_phrase_test.cpp
@@ -38,11 +38,11 @@ struct MyTerm : public search::queryeval::SimpleLeafBlueprint {
FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
return default_flow_stats(docid_limit, getState().estimate().estHits, 0);
}
- SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const override {
+ SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &) const override {
return {};
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
@@ -146,12 +146,14 @@ public:
void
fetchPostings(bool useBlueprint)
{
- ExecuteInfo execInfo = ExecuteInfo::createForTest(_strict);
+ ExecuteInfo execInfo = ExecuteInfo::FULL;
if (useBlueprint) {
+ _phrase.basic_plan(_strict, 100);
_phrase.fetchPostings(execInfo);
return;
}
for (const auto & i : _children) {
+ i->basic_plan(_strict, 100);
i->fetchPostings(execInfo);
}
}
@@ -160,7 +162,7 @@ public:
SearchIterator *createSearch(bool useBlueprint) {
SearchIterator::UP search;
if (useBlueprint) {
- search = _phrase.createSearch(*_md, _strict);
+ search = _phrase.createSearch(*_md);
} else {
search::fef::TermFieldMatchDataArray childMatch;
for (size_t i = 0; i < _children.size(); ++i) {
@@ -171,7 +173,7 @@ public:
}
SimplePhraseSearch::Children children;
for (const auto & i : _children) {
- children.push_back(i->createSearch(*_md, _strict));
+ children.push_back(i->createSearch(*_md));
}
search = std::make_unique<SimplePhraseSearch>(std::move(children),
MatchData::UP(), childMatch, _order,
diff --git a/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp b/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp
index a266902445b..b84cb02a357 100644
--- a/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp
+++ b/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp
@@ -76,8 +76,9 @@ TEST(SourceBlenderTest, test_strictness)
blend_b->addChild(std::move(a_b));
blend_b->addChild(std::move(b_b));
Blueprint::UP bp(blend_b);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- SearchIterator::UP search = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 100);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ SearchIterator::UP search = bp->createSearch(*md);
search->initFullRange();
SearchIterator &blend = *search;
diff --git a/searchlib/src/tests/queryeval/termwise_eval/termwise_eval_test.cpp b/searchlib/src/tests/queryeval/termwise_eval/termwise_eval_test.cpp
index 2a3ce66dba6..310c6d628e3 100644
--- a/searchlib/src/tests/queryeval/termwise_eval/termwise_eval_test.cpp
+++ b/searchlib/src/tests/queryeval/termwise_eval/termwise_eval_test.cpp
@@ -86,13 +86,11 @@ struct MyBlueprint : SimpleLeafBlueprint {
FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
return default_flow_stats(docid_limit, getState().estimate().estHits, 0);
}
- SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &,
- bool strict) const override
- {
- return std::make_unique<MyTerm>(hits, strict);
+ SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &) const override {
+ return std::make_unique<MyTerm>(hits, strict());
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
@@ -416,7 +414,8 @@ TEST(TermwiseEvalTest, require_that_basic_termwise_evaluation_works)
my_or.addChild(UP(new MyBlueprint({1}, true, 1)));
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
make_termwise(OR({ TERM({1}, strict), TERM({2}, strict) }, strict), strict)->asString());
}
}
@@ -431,7 +430,8 @@ TEST(TermwiseEvalTest, require_that_the_hit_rate_must_be_high_enough_for_termwis
my_or.addChild(UP(new MyBlueprint({1}, true, 1)));
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
for (bool strict: {true, false}) {
- EXPECT_TRUE(my_or.createSearch(*md, strict)->asString().find("TermwiseSearch") == vespalib::string::npos);
+ my_or.basic_plan(strict, 100);
+ EXPECT_TRUE(my_or.createSearch(*md)->asString().find("TermwiseSearch") == vespalib::string::npos);
}
}
@@ -446,7 +446,8 @@ TEST(TermwiseEvalTest, require_that_enough_unranked_termwise_terms_are_present_f
my_or.addChild(UP(new MyBlueprint({2}, false, 2))); // <- not termwise
my_or.addChild(UP(new MyBlueprint({3}, true, 3))); // <- ranked
for (bool strict: {true, false}) {
- EXPECT_TRUE(my_or.createSearch(*md, strict)->asString().find("TermwiseSearch") == vespalib::string::npos);
+ my_or.basic_plan(strict, 100);
+ EXPECT_TRUE(my_or.createSearch(*md)->asString().find("TermwiseSearch") == vespalib::string::npos);
}
}
@@ -464,7 +465,8 @@ TEST(TermwiseEvalTest, require_that_termwise_evaluation_can_be_multi_level_but_n
child->addChild(UP(new MyBlueprint({3}, true, 3)));
my_or.addChild(std::move(child));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
make_termwise(OR({ TERM({1}, strict),
ORz({ TERM({2}, strict), TERM({3}, strict) }, strict) },
strict), strict)->asString());
@@ -483,7 +485,8 @@ TEST(TermwiseEvalTest, require_that_or_can_be_completely_termwise)
my_or.addChild(UP(new MyBlueprint({1}, true, 1)));
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
make_termwise(OR({ TERM({1}, strict), TERM({2}, strict) }, strict), strict)->asString());
}
}
@@ -499,7 +502,8 @@ TEST(TermwiseEvalTest, require_that_or_can_be_partially_termwise)
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
my_or.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
ORs({ make_termwise(OR({ TERM({1}, strict), TERM({3}, strict) }, strict), strict),
TERM({2}, strict) }, strict)->asString());
}
@@ -516,7 +520,8 @@ TEST(TermwiseEvalTest, require_that_or_puts_termwise_subquery_at_the_right_place
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
my_or.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
ORs({ TERM({1}, strict),
make_termwise(OR({ TERM({2}, strict), TERM({3}, strict) }, strict),
strict) }, strict)->asString());
@@ -535,7 +540,8 @@ TEST(TermwiseEvalTest, require_that_or_can_use_termwise_eval_also_when_having_no
my_or.addChild(UP(new MyBlueprint({2}, true, 2)));
my_or.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_or.createSearch(*md, strict)->asString(),
+ my_or.basic_plan(strict, 100);
+ EXPECT_EQ(my_or.createSearch(*md)->asString(),
ORz({ TERM({1}, strict),
make_termwise(OR({ TERM({2}, strict), TERM({3}, strict) }, strict),
strict)},
@@ -555,7 +561,8 @@ TEST(TermwiseEvalTest, require_that_and_can_be_completely_termwise)
my_and.addChild(UP(new MyBlueprint({1}, true, 1)));
my_and.addChild(UP(new MyBlueprint({2}, true, 2)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_and.createSearch(*md, strict)->asString(),
+ my_and.basic_plan(strict, 100);
+ EXPECT_EQ(my_and.createSearch(*md)->asString(),
make_termwise(AND({ TERM({1}, strict), TERM({2}, false) }, strict), strict)->asString());
}
}
@@ -571,7 +578,8 @@ TEST(TermwiseEvalTest, require_that_and_can_be_partially_termwise)
my_and.addChild(UP(new MyBlueprint({2}, true, 2)));
my_and.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_and.createSearch(*md, strict)->asString(),
+ my_and.basic_plan(strict, 100);
+ EXPECT_EQ(my_and.createSearch(*md)->asString(),
ANDs({ make_termwise(AND({ TERM({1}, strict), TERM({3}, false) },
strict),
strict),
@@ -590,7 +598,8 @@ TEST(TermwiseEvalTest, require_that_and_puts_termwise_subquery_at_the_right_plac
my_and.addChild(UP(new MyBlueprint({2}, true, 2)));
my_and.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_and.createSearch(*md, strict)->asString(),
+ my_and.basic_plan(strict, 100);
+ EXPECT_EQ(my_and.createSearch(*md)->asString(),
ANDs({ TERM({1}, strict),
make_termwise(AND({ TERM({2}, false), TERM({3}, false) }, false),
false) }, strict)->asString());
@@ -609,7 +618,8 @@ TEST(TermwiseEvalTest, require_that_and_can_use_termwise_eval_also_when_having_n
my_and.addChild(UP(new MyBlueprint({2}, true, 2)));
my_and.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_and.createSearch(*md, strict)->asString(),
+ my_and.basic_plan(strict, 100);
+ EXPECT_EQ(my_and.createSearch(*md)->asString(),
ANDz({ TERM({1}, strict),
make_termwise(AND({ TERM({2}, false), TERM({3}, false) }, false),
false) }, strict)->asString());
@@ -627,7 +637,8 @@ TEST(TermwiseEvalTest, require_that_andnot_can_be_completely_termwise)
my_andnot.addChild(UP(new MyBlueprint({1}, true, 1)));
my_andnot.addChild(UP(new MyBlueprint({2}, true, 2)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_andnot.createSearch(*md, strict)->asString(),
+ my_andnot.basic_plan(strict, 100);
+ EXPECT_EQ(my_andnot.createSearch(*md)->asString(),
make_termwise(ANDNOT({ TERM({1}, strict), TERM({2}, false) },
strict), strict)->asString());
}
@@ -642,7 +653,8 @@ TEST(TermwiseEvalTest, require_that_andnot_can_be_partially_termwise)
my_andnot.addChild(UP(new MyBlueprint({2}, true, 2)));
my_andnot.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_andnot.createSearch(*md, strict)->asString(),
+ my_andnot.basic_plan(strict, 100);
+ EXPECT_EQ(my_andnot.createSearch(*md)->asString(),
ANDNOT({ TERM({1}, strict),
make_termwise(OR({ TERM({2}, false), TERM({3}, false) }, false),
false) }, strict)->asString());
@@ -659,7 +671,8 @@ TEST(TermwiseEvalTest, require_that_andnot_can_be_partially_termwise_with_first_
my_andnot.addChild(UP(new MyBlueprint({2}, false, 2)));
my_andnot.addChild(UP(new MyBlueprint({3}, true, 3)));
for (bool strict: {true, false}) {
- EXPECT_EQ(my_andnot.createSearch(*md, strict)->asString(),
+ my_andnot.basic_plan(strict, 100);
+ EXPECT_EQ(my_andnot.createSearch(*md)->asString(),
ANDNOT({ make_termwise(ANDNOT({ TERM({1}, strict), TERM({3}, false) }, strict),
strict),
TERM({2}, false) }, strict)->asString());
diff --git a/searchlib/src/tests/queryeval/weighted_set_term/weighted_set_term_test.cpp b/searchlib/src/tests/queryeval/weighted_set_term/weighted_set_term_test.cpp
index 54663e48060..57e41fef13b 100644
--- a/searchlib/src/tests/queryeval/weighted_set_term/weighted_set_term_test.cpp
+++ b/searchlib/src/tests/queryeval/weighted_set_term/weighted_set_term_test.cpp
@@ -69,8 +69,9 @@ struct WS {
FieldSpecList fields;
fields.add(FieldSpec(field, fieldId, handle));
auto bp = searchable.createBlueprint(requestContext, fields, *node);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- auto sb = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 1000);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ auto sb = bp->createSearch(*md);
return (dynamic_cast<WeightedSetTermSearch*>(sb.get()) != nullptr);
}
@@ -84,8 +85,9 @@ struct WS {
FieldSpecList fields;
fields.add(FieldSpec(field, fieldId, handle, field_is_filter));
auto bp = searchable.createBlueprint(requestContext, fields, *node);
- bp->fetchPostings(ExecuteInfo::createForTest(strict));
- auto sb = bp->createSearch(*md, strict);
+ bp->basic_plan(strict, 1000);
+ bp->fetchPostings(ExecuteInfo::FULL);
+ auto sb = bp->createSearch(*md);
sb->initFullRange();
FakeResult result;
for (uint32_t docId = 1; docId < 10; ++docId) {
@@ -333,7 +335,7 @@ struct VerifyMatchData {
VerifyMatchData &vmd;
MyBlueprint(VerifyMatchData &vmd_in, FieldSpecBase spec_in)
: SimpleLeafBlueprint(spec_in), vmd(vmd_in) {}
- [[nodiscard]] SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool) const override {
+ [[nodiscard]] SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override {
EXPECT_EQ(tfmda.size(), 1u);
EXPECT_TRUE(tfmda[0] != nullptr);
if (vmd.child_tfmd == nullptr) {
@@ -347,8 +349,8 @@ struct VerifyMatchData {
FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
return default_flow_stats(docid_limit, 0, 0);
}
- [[nodiscard]] SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ [[nodiscard]] SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
size_t child_cnt = 0;
@@ -371,7 +373,12 @@ TEST(WeightedSetTermTest, require_that_children_get_a_common_yet_separate_term_f
}
blueprint.complete(estimate);
auto match_data = layout.createMatchData();
- auto search = blueprint.createSearch(*match_data, true);
+ blueprint.basic_plan(true, 1000);
+ {
+ Blueprint &bp = blueprint;
+ bp.fetchPostings(ExecuteInfo::FULL);
+ }
+ auto search = blueprint.createSearch(*match_data);
auto top_tfmd = match_data->resolveTermField(top_handle);
EXPECT_EQ(vmd.child_cnt, 5u);
EXPECT_TRUE(vmd.child_tfmd != nullptr);
diff --git a/searchlib/src/vespa/searchcommon/attribute/i_search_context.h b/searchlib/src/vespa/searchcommon/attribute/i_search_context.h
index 8ea6f0f60af..a4703232c2b 100644
--- a/searchlib/src/vespa/searchcommon/attribute/i_search_context.h
+++ b/searchlib/src/vespa/searchcommon/attribute/i_search_context.h
@@ -48,7 +48,7 @@ public:
* Create temporary posting lists.
* Should be called before createIterator() is called.
*/
- virtual void fetchPostings(const queryeval::ExecuteInfo &execInfo) = 0;
+ virtual void fetchPostings(const queryeval::ExecuteInfo &execInfo, bool strict) = 0;
virtual bool valid() const = 0;
virtual Int64Range getAsIntegerTerm() const = 0;
diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp b/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp
index e70c498d3c3..707b98b1cf3 100644
--- a/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp
@@ -170,26 +170,26 @@ public:
}
}
- SearchIteratorUP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override {
+ SearchIteratorUP createLeafSearch(const TermFieldMatchDataArray &tfmda) const override {
assert(tfmda.size() == 1);
- return _search_context->createIterator(tfmda[0], strict);
+ return _search_context->createIterator(tfmda[0], strict());
}
- SearchIterator::UP createSearch(fef::MatchData &md, bool strict) const override {
+ SearchIterator::UP createSearch(fef::MatchData &md) const override {
const State &state = getState();
assert(state.numFields() == 1);
- return _search_context->createIterator(state.field(0).resolve(md), strict);
+ return _search_context->createIterator(state.field(0).resolve(md), strict());
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
(void) constraint; // We provide an iterator with exact results, so no need to take constraint into consideration.
auto wrapper = std::make_unique<FilterWrapper>(getState().numFields());
- wrapper->wrap(createLeafSearch(wrapper->tfmda(), strict));
+ wrapper->wrap(createLeafSearch(wrapper->tfmda()));
return wrapper;
}
void fetchPostings(const queryeval::ExecuteInfo &execInfo) override {
- _search_context->fetchPostings(execInfo);
+ _search_context->fetchPostings(execInfo, strict());
}
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
@@ -287,6 +287,9 @@ public:
bool should_use() const { return _should_use; }
+ void sort(queryeval::InFlow in_flow, const Options &) override {
+ strict(in_flow.strict());
+ }
queryeval::FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
using OrFlow = search::queryeval::OrFlow;
struct MyAdapter {
@@ -306,13 +309,13 @@ public:
}
SearchIterator::UP
- createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override
+ createLeafSearch(const TermFieldMatchDataArray &tfmda) const override
{
OrSearch::Children children;
for (auto & search : _rangeSearches) {
- children.push_back(search->createIterator(tfmda[0], strict));
+ children.push_back(search->createIterator(tfmda[0], strict()));
}
- if (strict) {
+ if (strict()) {
if (children.size() < 0x70) {
using Parent = StrictHeapOrSearch<NoUnpack, vespalib::LeftArrayHeap, uint8_t>;
return std::make_unique<LocationPreFilterIterator<true, Parent>>(std::move(children));
@@ -325,13 +328,13 @@ public:
return std::make_unique<LocationPreFilterIterator<false, Parent>>(std::move(children));
}
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
void fetchPostings(const queryeval::ExecuteInfo &execInfo) override {
for (auto & search : _rangeSearches) {
- search->fetchPostings(execInfo);
+ search->fetchPostings(execInfo, strict());
}
}
@@ -371,24 +374,28 @@ public:
const common::Location &location() const { return _location; }
+ void sort(queryeval::InFlow in_flow, const Options &) override {
+ strict(in_flow.strict());
+ }
+
queryeval::FlowStats calculate_flow_stats(uint32_t) const override {
return default_flow_stats(0);
}
SearchIterator::UP
- createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override
+ createLeafSearch(const TermFieldMatchDataArray &tfmda) const override
{
if (tfmda.size() == 1) {
// search in exactly one field
fef::TermFieldMatchData &tfmd = *tfmda[0];
- return common::create_location_iterator(tfmd, _attribute.getNumDocs(), strict, _location);
+ return common::create_location_iterator(tfmd, _attribute.getNumDocs(), strict(), _location);
} else {
LOG(debug, "wrong size tfmda: %zu (fallback to old location iterator)\n", tfmda.size());
}
- return FastS_AllocLocationIterator(_attribute.getNumDocs(), strict, _location);
+ return FastS_AllocLocationIterator(_attribute.getNumDocs(), strict(), _location);
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
void visitMembers(vespalib::ObjectVisitor& visitor) const override {
LeafBlueprint::visitMembers(visitor);
@@ -500,6 +507,10 @@ public:
setEstimate(estimate);
}
+ void sort(queryeval::InFlow in_flow, const Options &) override {
+ strict(in_flow.strict());
+ }
+
queryeval::FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
using OrFlow = search::queryeval::OrFlow;
struct MyAdapter {
@@ -523,7 +534,7 @@ public:
OrFlow::cost_of(MyAdapter(docid_limit), _terms, true) + queryeval::flow::heap_cost(est, _terms.size())};
}
- SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override {
+ SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda) const override {
assert(tfmda.size() == 1);
if (_terms.empty()) {
return std::make_unique<queryeval::EmptySearch>();
@@ -531,17 +542,17 @@ public:
return queryeval::ParallelWeakAndSearch::create(*tfmda[0],
queryeval::ParallelWeakAndSearch::MatchParams(_scores, _scoreThreshold,
_thresholdBoostFactor, _scoresAdjustFrequency)
- .setDocIdLimit(get_docid_limit()),
- _weights, _terms, _attr, strict);
+ .setDocIdLimit(get_docid_limit()),
+ _weights, _terms, _attr, strict());
}
- std::unique_ptr<SearchIterator> createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ std::unique_ptr<SearchIterator> createFilterSearch(FilterConstraint constraint) const override;
bool always_needs_unpack() const override { return true; }
};
DirectWandBlueprint::~DirectWandBlueprint() = default;
std::unique_ptr<SearchIterator>
-DirectWandBlueprint::createFilterSearch(bool, FilterConstraint constraint) const
+DirectWandBlueprint::createFilterSearch(FilterConstraint constraint) const
{
if (constraint == Blueprint::FilterConstraint::UPPER_BOUND) {
std::vector<DocidWithWeightIterator> iterators;
diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.cpp b/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.cpp
index 18748641ca4..81a7a06030e 100644
--- a/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.cpp
@@ -121,6 +121,12 @@ AttributeWeightedSetBlueprint::addToken(std::unique_ptr<ISearchContext> context,
_contexts.push_back(context.release());
}
+void
+AttributeWeightedSetBlueprint::sort(queryeval::InFlow in_flow, const Options &)
+{
+ strict(in_flow.strict());
+}
+
queryeval::FlowStats
AttributeWeightedSetBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -141,16 +147,16 @@ AttributeWeightedSetBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
queryeval::SearchIterator::UP
-AttributeWeightedSetBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const
+AttributeWeightedSetBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
assert(getState().numFields() == 1);
fef::TermFieldMatchData &tfmd = *tfmda[0];
bool field_is_filter = getState().fields()[0].isFilter();
if ((tfmd.isNotNeeded() || field_is_filter) && (_contexts.size() == 1)) {
- return _contexts[0]->createIterator(&tfmd, strict);
+ return _contexts[0]->createIterator(&tfmd, strict());
}
- if (strict) { // use generic weighted set search
+ if (strict()) { // use generic weighted set search
fef::MatchDataLayout layout;
auto handle = layout.allocTermField(tfmd.getFieldId());
auto match_data = layout.createMatchData();
@@ -174,24 +180,24 @@ AttributeWeightedSetBlueprint::createLeafSearch(const fef::TermFieldMatchDataArr
}
queryeval::SearchIterator::UP
-AttributeWeightedSetBlueprint::createFilterSearch(bool strict, FilterConstraint) const
+AttributeWeightedSetBlueprint::createFilterSearch(FilterConstraint) const
{
std::vector<std::unique_ptr<queryeval::SearchIterator>> children;
children.reserve(_contexts.size());
for (auto& context : _contexts) {
auto wrapper = std::make_unique<queryeval::FilterWrapper>(1);
- wrapper->wrap(context->createIterator(wrapper->tfmda()[0], strict));
+ wrapper->wrap(context->createIterator(wrapper->tfmda()[0], strict()));
children.emplace_back(std::move(wrapper));
}
- return queryeval::OrSearch::create(std::move(children), strict, queryeval::UnpackInfo());
+ return queryeval::OrSearch::create(std::move(children), strict(), queryeval::UnpackInfo());
}
void
AttributeWeightedSetBlueprint::fetchPostings(const queryeval::ExecuteInfo &execInfo)
{
- if (execInfo.is_strict()) {
+ if (strict()) {
for (auto * context : _contexts) {
- context->fetchPostings(execInfo);
+ context->fetchPostings(execInfo, strict());
}
}
}
diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.h b/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.h
index 32632403e42..18cfd6ed5ce 100644
--- a/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.h
+++ b/searchlib/src/vespa/searchlib/attribute/attribute_weighted_set_blueprint.h
@@ -31,9 +31,10 @@ public:
AttributeWeightedSetBlueprint(const queryeval::FieldSpec &field, const IAttributeVector & attr);
~AttributeWeightedSetBlueprint();
void addToken(std::unique_ptr<ISearchContext> context, int32_t weight);
+ void sort(queryeval::InFlow in_flow, const Options &opts) override;
queryeval::FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- queryeval::SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- queryeval::SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ queryeval::SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ queryeval::SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
void fetchPostings(const queryeval::ExecuteInfo &execInfo) override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
};
diff --git a/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.h b/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.h
index 5aafe4af72b..7dfc7fe3a78 100644
--- a/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.h
+++ b/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.h
@@ -72,6 +72,10 @@ public:
setEstimate(estimate);
}
+ void sort(queryeval::InFlow in_flow, const Options &) override {
+ strict(in_flow.strict());
+ }
+
queryeval::FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
using OrFlow = search::queryeval::OrFlow;
struct MyAdapter {
@@ -93,9 +97,9 @@ public:
OrFlow::cost_of(MyAdapter(docid_limit), _terms, true) + queryeval::flow::heap_cost(est, _terms.size())};
}
- std::unique_ptr<queryeval::SearchIterator> createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool) const override;
+ std::unique_ptr<queryeval::SearchIterator> createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
- std::unique_ptr<queryeval::SearchIterator> createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ std::unique_ptr<queryeval::SearchIterator> createFilterSearch(FilterConstraint constraint) const override;
std::unique_ptr<queryeval::MatchingElementsSearch> create_matching_elements_search(const MatchingElementsFields &fields) const override {
if (fields.has_field(_iattr.getName())) {
return queryeval::MatchingElementsSearch::create(_iattr, _dictionary_snapshot, vespalib::ConstArrayRef<IDirectPostingStore::LookupResult>(_terms));
diff --git a/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.hpp b/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.hpp
index 0a3b24142a5..817eab3e070 100644
--- a/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/direct_multi_term_blueprint.hpp
@@ -164,20 +164,20 @@ DirectMultiTermBlueprint<PostingStoreType, SearchType>::create_search_helper(con
template <typename PostingStoreType, typename SearchType>
std::unique_ptr<queryeval::SearchIterator>
-DirectMultiTermBlueprint<PostingStoreType, SearchType>::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const
+DirectMultiTermBlueprint<PostingStoreType, SearchType>::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
assert(getState().numFields() == 1);
- return create_search_helper<SearchType::filter_search>(tfmda, strict);
+ return create_search_helper<SearchType::filter_search>(tfmda, strict());
}
template <typename PostingStoreType, typename SearchType>
std::unique_ptr<queryeval::SearchIterator>
-DirectMultiTermBlueprint<PostingStoreType, SearchType>::createFilterSearch(bool strict, FilterConstraint) const
+DirectMultiTermBlueprint<PostingStoreType, SearchType>::createFilterSearch(FilterConstraint) const
{
assert(getState().numFields() == 1);
auto wrapper = std::make_unique<FilterWrapper>(getState().numFields());
- wrapper->wrap(create_search_helper<true>(wrapper->tfmda(), strict));
+ wrapper->wrap(create_search_helper<true>(wrapper->tfmda(), strict()));
return wrapper;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.cpp b/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.cpp
index 22362231cc1..62a845e79c4 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.cpp
@@ -41,7 +41,7 @@ EnumHintSearchContext::lookupRange(const vespalib::datastore::EntryComparator &l
}
void
-EnumHintSearchContext::fetchPostings(const queryeval::ExecuteInfo &)
+EnumHintSearchContext::fetchPostings(const queryeval::ExecuteInfo &, bool)
{
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.h b/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.h
index 23a0a6c560b..53feb4b5085 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.h
+++ b/searchlib/src/vespa/searchlib/attribute/enumhintsearchcontext.h
@@ -39,7 +39,7 @@ protected:
std::unique_ptr<queryeval::SearchIterator>
createPostingIterator(fef::TermFieldMatchData *matchData, bool strict) override;
- void fetchPostings(const queryeval::ExecuteInfo & execInfo) override;
+ void fetchPostings(const queryeval::ExecuteInfo & execInfo, bool strict) override;
HitEstimate calc_hit_estimate() const override;
uint32_t get_committed_docid_limit() const noexcept { return _docIdLimit; }
};
diff --git a/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp b/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp
index 79a021989fc..7829003da4b 100644
--- a/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/imported_search_context.cpp
@@ -305,10 +305,10 @@ ImportedSearchContext::considerAddSearchCacheEntry()
}
void
-ImportedSearchContext::fetchPostings(const queryeval::ExecuteInfo &execInfo) {
+ImportedSearchContext::fetchPostings(const queryeval::ExecuteInfo &execInfo, bool strict) {
if (!_searchCacheLookup) {
- _target_search_context->fetchPostings(execInfo);
- if (!_merger.merge_done() && (execInfo.is_strict() || (_target_attribute.getIsFastSearch() && execInfo.hit_rate() > 0.01))) {
+ _target_search_context->fetchPostings(execInfo, strict);
+ if (!_merger.merge_done() && (strict || (_target_attribute.getIsFastSearch() && execInfo.hit_rate() > 0.01))) {
makeMergedPostings(_target_attribute.getIsFilter());
considerAddSearchCacheEntry();
}
diff --git a/searchlib/src/vespa/searchlib/attribute/imported_search_context.h b/searchlib/src/vespa/searchlib/attribute/imported_search_context.h
index 305a8bf2379..45eff967547 100644
--- a/searchlib/src/vespa/searchlib/attribute/imported_search_context.h
+++ b/searchlib/src/vespa/searchlib/attribute/imported_search_context.h
@@ -66,7 +66,7 @@ public:
std::unique_ptr<queryeval::SearchIterator>
createIterator(fef::TermFieldMatchData* matchData, bool strict) override;
HitEstimate calc_hit_estimate() const override;
- void fetchPostings(const queryeval::ExecuteInfo &execInfo) override;
+ void fetchPostings(const queryeval::ExecuteInfo &execInfo, bool strict) override;
bool valid() const override;
Int64Range getAsIntegerTerm() const override;
DoubleRange getAsDoubleTerm() const override;
diff --git a/searchlib/src/vespa/searchlib/attribute/ipostinglistsearchcontext.h b/searchlib/src/vespa/searchlib/attribute/ipostinglistsearchcontext.h
index ac1abc56329..e0cdc38076d 100644
--- a/searchlib/src/vespa/searchlib/attribute/ipostinglistsearchcontext.h
+++ b/searchlib/src/vespa/searchlib/attribute/ipostinglistsearchcontext.h
@@ -29,7 +29,7 @@ protected:
virtual ~IPostingListSearchContext() { }
public:
- virtual void fetchPostings(const queryeval::ExecuteInfo & execInfo) = 0;
+ virtual void fetchPostings(const queryeval::ExecuteInfo & execInfo, bool strict) = 0;
virtual std::unique_ptr<queryeval::SearchIterator> createPostingIterator(fef::TermFieldMatchData *matchData, bool strict) = 0;
virtual HitEstimate calc_hit_estimate() const = 0;
};
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
index 41a12dce756..5518d60f25f 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.h
@@ -110,7 +110,7 @@ protected:
virtual void fillArray();
virtual void fillBitVector(const ExecuteInfo &);
- void fetchPostings(const ExecuteInfo & strict) override;
+ void fetchPostings(const ExecuteInfo &exec, bool strict) override;
// this will be called instead of the fetchPostings function in some cases
void diversify(bool forward, size_t wanted_hits, const IAttributeVector &diversity_attr,
size_t max_per_group, size_t cutoff_groups, bool cutoff_strict);
@@ -224,7 +224,7 @@ private:
? HitEstimate(limit)
: estimate;
}
- void fetchPostings(const ExecuteInfo & execInfo) override {
+ void fetchPostings(const ExecuteInfo & execInfo, bool strict) override {
if (params().diversityAttribute() != nullptr) {
bool forward = (this->getRangeLimit() > 0);
size_t wanted_hits = std::abs(this->getRangeLimit());
@@ -232,7 +232,7 @@ private:
*(params().diversityAttribute()), this->getMaxPerGroup(),
params().diversityCutoffGroups(), params().diversityCutoffStrict());
} else {
- PostingListSearchContextT<DataT>::fetchPostings(execInfo);
+ PostingListSearchContextT<DataT>::fetchPostings(execInfo, strict);
}
}
diff --git a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
index 77f773d0469..0ea17ab1d1e 100644
--- a/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
+++ b/searchlib/src/vespa/searchlib/attribute/postinglistsearchcontext.hpp
@@ -137,7 +137,7 @@ PostingListSearchContextT<DataT>::fillBitVector(const ExecuteInfo & exec_info)
template <typename DataT>
void
-PostingListSearchContextT<DataT>::fetchPostings(const ExecuteInfo & exec_info)
+PostingListSearchContextT<DataT>::fetchPostings(const ExecuteInfo & exec_info, bool strict)
{
// The following constant is derived after running parts of
// the range search performance test with 10M documents on an Apple M1 Pro with 32 GB memory.
@@ -168,7 +168,7 @@ PostingListSearchContextT<DataT>::fetchPostings(const ExecuteInfo & exec_info)
// The threshold for when to use array merging is therefore 0.0025 (0.08 / 32).
constexpr float threshold_for_using_array = 0.0025;
if (!_merger.merge_done() && _uniqueValues >= 2u && this->_dictionary.get_has_btree_dictionary()) {
- if (exec_info.is_strict() || use_posting_lists_when_non_strict(exec_info)) {
+ if (strict || use_posting_lists_when_non_strict(exec_info)) {
size_t sum = estimated_hits_in_range();
//TODO Honour soft_doom and forward it to merge code
if (sum < (_docIdLimit * threshold_for_using_array)) {
diff --git a/searchlib/src/vespa/searchlib/attribute/search_context.cpp b/searchlib/src/vespa/searchlib/attribute/search_context.cpp
index 0c0318bf1e3..2b68cf58ae6 100644
--- a/searchlib/src/vespa/searchlib/attribute/search_context.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/search_context.cpp
@@ -50,10 +50,10 @@ SearchContext::createFilterIterator(fef::TermFieldMatchData* matchData, bool str
void
-SearchContext::fetchPostings(const queryeval::ExecuteInfo& execInfo)
+SearchContext::fetchPostings(const queryeval::ExecuteInfo& execInfo, bool strict)
{
if (_plsc != nullptr) {
- _plsc->fetchPostings(execInfo);
+ _plsc->fetchPostings(execInfo, strict);
}
}
diff --git a/searchlib/src/vespa/searchlib/attribute/search_context.h b/searchlib/src/vespa/searchlib/attribute/search_context.h
index a18e15ae8f4..1b17a27b6db 100644
--- a/searchlib/src/vespa/searchlib/attribute/search_context.h
+++ b/searchlib/src/vespa/searchlib/attribute/search_context.h
@@ -34,7 +34,7 @@ public:
HitEstimate calc_hit_estimate() const override;
std::unique_ptr<queryeval::SearchIterator> createIterator(fef::TermFieldMatchData* matchData, bool strict) override;
- void fetchPostings(const queryeval::ExecuteInfo& execInfo) override;
+ void fetchPostings(const queryeval::ExecuteInfo& execInfo, bool strict) override;
bool valid() const override { return false; }
Int64Range getAsIntegerTerm() const override { return Int64Range(); }
DoubleRange getAsDoubleTerm() const override { return DoubleRange(); }
diff --git a/searchlib/src/vespa/searchlib/attribute/singleboolattribute.cpp b/searchlib/src/vespa/searchlib/attribute/singleboolattribute.cpp
index 4713f452adc..b635e207a4f 100644
--- a/searchlib/src/vespa/searchlib/attribute/singleboolattribute.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/singleboolattribute.cpp
@@ -130,7 +130,7 @@ public:
std::unique_ptr<queryeval::SearchIterator>
createFilterIterator(fef::TermFieldMatchData * matchData, bool strict) override;
- void fetchPostings(const queryeval::ExecuteInfo &execInfo) override;
+ void fetchPostings(const queryeval::ExecuteInfo &execInfo, bool strict) override;
std::unique_ptr<queryeval::SearchIterator> createPostingIterator(fef::TermFieldMatchData *matchData, bool strict) override;
HitEstimate calc_hit_estimate() const override;
uint32_t get_committed_docid_limit() const noexcept override;
@@ -162,7 +162,7 @@ BitVectorSearchContext::createFilterIterator(fef::TermFieldMatchData * matchData
}
void
-BitVectorSearchContext::fetchPostings(const queryeval::ExecuteInfo &) {
+BitVectorSearchContext::fetchPostings(const queryeval::ExecuteInfo &, bool) {
}
std::unique_ptr<queryeval::SearchIterator>
diff --git a/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.cpp b/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.cpp
index 99be653a398..c0d0b1baa8c 100644
--- a/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.cpp
+++ b/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.cpp
@@ -76,12 +76,12 @@ DiskTermBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-DiskTermBlueprint::createLeafSearch(const TermFieldMatchDataArray & tfmda, bool strict) const
+DiskTermBlueprint::createLeafSearch(const TermFieldMatchDataArray & tfmda) const
{
if (_bitVector && (_useBitVector || tfmda[0]->isNotNeeded())) {
LOG(debug, "Return BitVectorIterator: %s, wordNum(%" PRIu64 "), docCount(%" PRIu64 ")",
getName(_lookupRes->indexId).c_str(), _lookupRes->wordNum, _lookupRes->counts._numDocs);
- return BitVectorIterator::create(_bitVector.get(), *tfmda[0], strict);
+ return BitVectorIterator::create(_bitVector.get(), *tfmda[0], strict());
}
SearchIterator::UP search(_postingHandle->createIterator(_lookupRes->counts, tfmda, _useBitVector));
if (_useBitVector) {
@@ -95,12 +95,12 @@ DiskTermBlueprint::createLeafSearch(const TermFieldMatchDataArray & tfmda, bool
}
SearchIterator::UP
-DiskTermBlueprint::createFilterSearch(bool strict, FilterConstraint) const
+DiskTermBlueprint::createFilterSearch(FilterConstraint) const
{
auto wrapper = std::make_unique<queryeval::FilterWrapper>(getState().numFields());
auto & tfmda = wrapper->tfmda();
if (_bitVector) {
- wrapper->wrap(BitVectorIterator::create(_bitVector.get(), *tfmda[0], strict));
+ wrapper->wrap(BitVectorIterator::create(_bitVector.get(), *tfmda[0], strict()));
} else {
wrapper->wrap(_postingHandle->createIterator(_lookupRes->counts, tfmda, _useBitVector));
}
diff --git a/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.h b/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.h
index a8754663aab..abdecf29c45 100644
--- a/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.h
+++ b/searchlib/src/vespa/searchlib/diskindex/disktermblueprint.h
@@ -41,11 +41,11 @@ public:
// Inherit doc from Blueprint.
// For now, this DiskTermBlueprint instance must have longer lifetime than the created iterator.
- std::unique_ptr<queryeval::SearchIterator> createLeafSearch(const fef::TermFieldMatchDataArray & tfmda, bool strict) const override;
+ std::unique_ptr<queryeval::SearchIterator> createLeafSearch(const fef::TermFieldMatchDataArray & tfmda) const override;
void fetchPostings(const queryeval::ExecuteInfo &execInfo) override;
- std::unique_ptr<queryeval::SearchIterator> createFilterSearch(bool strict, FilterConstraint) const override;
+ std::unique_ptr<queryeval::SearchIterator> createFilterSearch(FilterConstraint) const override;
void visitMembers(vespalib::ObjectVisitor& visitor) const override;
};
diff --git a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
index e2bb5e76751..eba135d8519 100644
--- a/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
+++ b/searchlib/src/vespa/searchlib/memoryindex/field_index.cpp
@@ -264,7 +264,7 @@ public:
return {rel_est, btree_cost(), btree_strict_cost(rel_est)};
}
- SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray& tfmda, bool) const override {
+ SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray& tfmda) const override {
auto result = make_search_iterator<interleaved_features>(_posting_itr, _feature_store, _field_id, tfmda);
if (_use_bit_vector) {
LOG(debug, "Return BooleanMatchIteratorWrapper: field_id(%u), doc_count(%zu)",
@@ -276,7 +276,7 @@ public:
return result;
}
- SearchIterator::UP createFilterSearch(bool, FilterConstraint) const override {
+ SearchIterator::UP createFilterSearch(FilterConstraint) const override {
auto wrapper = std::make_unique<queryeval::FilterWrapper>(getState().numFields());
auto & tfmda = wrapper->tfmda();
wrapper->wrap(make_search_iterator<interleaved_features>(_posting_itr, _feature_store, _field_id, tfmda));
diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
index 5f3cf0567bc..78bcd33fcb4 100644
--- a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
@@ -121,12 +121,41 @@ Blueprint::Blueprint() noexcept
_flow_stats(0.0, 0.0, 0.0),
_sourceId(0xffffffff),
_docid_limit(0),
+ _strict(false),
_frozen(false)
{
}
Blueprint::~Blueprint() = default;
+void
+Blueprint::each_node_post_order(const std::function<void(Blueprint&)> &f)
+{
+ f(*this);
+}
+
+void
+Blueprint::basic_plan(InFlow in_flow, uint32_t docid_limit)
+{
+ setDocIdLimit(docid_limit);
+ each_node_post_order([docid_limit](Blueprint &bp){
+ bp.update_flow_stats(docid_limit);
+ });
+ auto opts = Options().sort_by_cost(true);
+ sort(in_flow, opts);
+}
+
+void
+Blueprint::null_plan(InFlow in_flow, uint32_t docid_limit)
+{
+ setDocIdLimit(docid_limit);
+ each_node_post_order([docid_limit](Blueprint &bp){
+ bp.update_flow_stats(docid_limit);
+ });
+ auto opts = Options().sort_by_cost(true).keep_order(true);
+ sort(in_flow, opts);
+}
+
Blueprint::UP
Blueprint::optimize(Blueprint::UP bp) {
Blueprint *root = bp.release();
@@ -194,10 +223,6 @@ Blueprint::FilterConstraint invert(Blueprint::FilterConstraint constraint) {
abort();
}
-template <typename Op> bool inherit_strict(size_t);
-template <> bool inherit_strict<AndSearch>(size_t i) { return (i == 0); }
-template <> bool inherit_strict<OrSearch>(size_t) { return true; }
-
template <typename Op> bool should_short_circuit(Trinary);
template <> bool should_short_circuit<AndSearch>(Trinary matches_any) { return (matches_any == Trinary::False); }
template <> bool should_short_circuit<OrSearch>(Trinary matches_any) { return (matches_any == Trinary::True); }
@@ -217,8 +242,7 @@ create_op_filter(const Blueprint::Children &children, bool strict, Blueprint::Fi
std::unique_ptr<SearchIterator> spare;
list.reserve(children.size());
for (size_t i = 0; i < children.size(); ++i) {
- auto strict_child = strict && inherit_strict<Op>(i);
- auto filter = children[i]->createFilterSearch(strict_child, constraint);
+ auto filter = children[i]->createFilterSearch(constraint);
auto matches_any = filter->matches_any();
if (should_short_circuit<Op>(matches_any)) {
return filter;
@@ -281,14 +305,14 @@ Blueprint::create_andnot_filter(const Children &children, bool strict, Blueprint
MultiSearch::Children list;
list.reserve(children.size());
{
- auto filter = children[0]->createFilterSearch(strict, constraint);
+ auto filter = children[0]->createFilterSearch(constraint);
if (filter->matches_any() == Trinary::False) {
return filter;
}
list.push_back(std::move(filter));
}
for (size_t i = 1; i < children.size(); ++i) {
- auto filter = children[i]->createFilterSearch(false, invert(constraint));
+ auto filter = children[i]->createFilterSearch(invert(constraint));
auto matches_any = filter->matches_any();
if (matches_any == Trinary::True) {
return std::make_unique<EmptySearch>();
@@ -305,14 +329,14 @@ Blueprint::create_andnot_filter(const Children &children, bool strict, Blueprint
}
std::unique_ptr<SearchIterator>
-Blueprint::create_first_child_filter(const Children &children, bool strict, Blueprint::FilterConstraint constraint)
+Blueprint::create_first_child_filter(const Children &children, Blueprint::FilterConstraint constraint)
{
REQUIRE(!children.empty());
- return children[0]->createFilterSearch(strict, constraint);
+ return children[0]->createFilterSearch(constraint);
}
std::unique_ptr<SearchIterator>
-Blueprint::create_default_filter(bool, FilterConstraint constraint)
+Blueprint::create_default_filter(FilterConstraint constraint)
{
if (constraint == FilterConstraint::UPPER_BOUND) {
return std::make_unique<FullSearch>();
@@ -374,6 +398,7 @@ Blueprint::visitMembers(vespalib::ObjectVisitor &visitor) const
visitor.visitFloat("strict_cost", strict_cost());
visitor.visitInt("sourceId", _sourceId);
visitor.visitInt("docid_limit", _docid_limit);
+ // visitor.visitBool("strict", _strict);
}
namespace blueprint {
@@ -412,6 +437,15 @@ IntermediateBlueprint::setDocIdLimit(uint32_t limit) noexcept
}
}
+void
+IntermediateBlueprint::each_node_post_order(const std::function<void(Blueprint&)> &f)
+{
+ for (Blueprint::UP &child : _children) {
+ f(*child);
+ }
+ f(*this);
+}
+
Blueprint::HitEstimate
IntermediateBlueprint::calculateEstimate() const
{
@@ -568,17 +602,18 @@ IntermediateBlueprint::optimize(Blueprint* &self, OptimizePass pass)
maybe_eliminate_self(self, get_replacement());
}
-double
+void
IntermediateBlueprint::sort(InFlow in_flow, const Options &opts)
{
- sort(_children, in_flow.strict(), opts.sort_by_cost());
+ strict(in_flow.strict()); // authorative strict tag (->fetchPostings,->createSearch,->createFilterSearch)
+ if (!opts.keep_order()) [[likely]] {
+ sort(_children, in_flow.strict(), opts.sort_by_cost());
+ }
auto flow = my_flow(in_flow);
for (size_t i = 0; i < _children.size(); ++i) {
_children[i]->sort(InFlow(flow.strict(), flow.flow()), opts);
flow.add(_children[i]->estimate());
}
- // TODO: better cost estimate (due to known in-flow and eagerness)
- return in_flow.strict() ? strict_cost() : in_flow.rate() * cost();
}
void
@@ -592,15 +627,14 @@ IntermediateBlueprint::set_global_filter(const GlobalFilter &global_filter, doub
}
SearchIterator::UP
-IntermediateBlueprint::createSearch(fef::MatchData &md, bool strict) const
+IntermediateBlueprint::createSearch(fef::MatchData &md) const
{
MultiSearch::Children subSearches;
subSearches.reserve(_children.size());
for (size_t i = 0; i < _children.size(); ++i) {
- bool strictChild = (strict && inheritStrict(i));
- subSearches.push_back(_children[i]->createSearch(md, strictChild));
+ subSearches.push_back(_children[i]->createSearch(md));
}
- return createIntermediateSearch(std::move(subSearches), strict, md);
+ return createIntermediateSearch(std::move(subSearches), md);
}
IntermediateBlueprint::IntermediateBlueprint() noexcept = default;
@@ -645,11 +679,11 @@ IntermediateBlueprint::visitMembers(vespalib::ObjectVisitor &visitor) const
void
IntermediateBlueprint::fetchPostings(const ExecuteInfo &execInfo)
{
- auto flow = my_flow(InFlow(execInfo.is_strict(), execInfo.hit_rate()));
+ auto flow = my_flow(InFlow(strict(), execInfo.hit_rate()));
for (size_t i = 0; i < _children.size(); ++i) {
double nextHitRate = flow.flow();
Blueprint & child = *_children[i];
- child.fetchPostings(ExecuteInfo::create(execInfo.is_strict() && inheritStrict(i), nextHitRate, execInfo));
+ child.fetchPostings(ExecuteInfo::create(nextHitRate, execInfo));
flow.add(child.estimate());
}
}
@@ -738,7 +772,7 @@ LeafBlueprint::freeze()
}
SearchIterator::UP
-LeafBlueprint::createSearch(fef::MatchData &md, bool strict) const
+LeafBlueprint::createSearch(fef::MatchData &md) const
{
const State &state = getState();
fef::TermFieldMatchDataArray tfmda;
@@ -746,7 +780,7 @@ LeafBlueprint::createSearch(fef::MatchData &md, bool strict) const
for (size_t i = 0; i < state.numFields(); ++i) {
tfmda.add(state.field(i).resolve(md));
}
- return createLeafSearch(tfmda, strict);
+ return createLeafSearch(tfmda);
}
bool
@@ -765,13 +799,6 @@ LeafBlueprint::optimize(Blueprint* &self, OptimizePass pass)
maybe_eliminate_self(self, get_replacement());
}
-double
-LeafBlueprint::sort(InFlow in_flow, const Options &)
-{
- // TODO: better cost estimate (due to known in-flow and eagerness)
- return in_flow.strict() ? strict_cost() : in_flow.rate() * cost();
-}
-
void
LeafBlueprint::set_cost_tier(uint32_t value)
{
@@ -796,6 +823,12 @@ LeafBlueprint::set_tree_size(uint32_t value)
//-----------------------------------------------------------------------------
+void
+SimpleLeafBlueprint::sort(InFlow in_flow, const Options &)
+{
+ strict(in_flow.strict()); // authorative strict tag (->fetchPostings,->createSearch,->createFilterSearch)
+}
+
}
void visit(vespalib::ObjectVisitor &self, const vespalib::string &name,
diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h
index b2edfb8a3ba..0fc5c690a25 100644
--- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h
@@ -59,6 +59,7 @@ public:
private:
bool _sort_by_cost;
bool _allow_force_strict;
+ bool _keep_order;
public:
constexpr Options() noexcept
: _sort_by_cost(false),
@@ -73,8 +74,13 @@ public:
_allow_force_strict = value;
return *this;
}
- static constexpr Options all() noexcept {
- return Options().sort_by_cost(true).allow_force_strict(true);
+ constexpr bool keep_order() const noexcept { return _keep_order; }
+ constexpr Options &keep_order(bool value) noexcept {
+ _keep_order = value;
+ return *this;
+ }
+ static Options default_options() noexcept {
+ return Options().sort_by_cost(true);
}
};
@@ -205,6 +211,7 @@ private:
FlowStats _flow_stats;
uint32_t _sourceId;
uint32_t _docid_limit;
+ bool _strict;
bool _frozen;
protected:
@@ -218,6 +225,12 @@ protected:
_frozen = true;
}
+ // Should be called by sort; sort is responsible for propagating
+ // strict tagging throughout the blueprint tree. Note that calling
+ // this directly breaks some tests using leaf proxy decorators
+ // that are not able to forward the non-virtual call.
+ void strict(bool value) noexcept { _strict = value; }
+
public:
class IPredicate {
public:
@@ -246,13 +259,44 @@ public:
virtual void setDocIdLimit(uint32_t limit) noexcept { _docid_limit = limit; }
uint32_t get_docid_limit() const noexcept { return _docid_limit; }
+ bool strict() const noexcept { return _strict; }
+
+ virtual void each_node_post_order(const std::function<void(Blueprint&)> &f);
+
+ // The combination of 'optimize' (2 passes bottom-up) and 'sort'
+ // (1 pass top-down) is considered 'planning'. Flow stats are
+ // calculated during the last optimize pass (which itself requires
+ // knowledge about the docid limit) and strict tagging is done
+ // during sorting. Strict tagging is needed for fetchPostings
+ // (which also needs the estimate part of the flow stats),
+ // createSearch and createFilterSearch to work correctly. This
+ // means we always need to perform some form of planning.
+ //
+ // This function will perform basic planning. The docid limit will
+ // be tagged on all nodes, flow stats will be calculated for all
+ // nodes, sorting will be performed based on optimal flow cost and
+ // strict tagging will be conservative. The only structural change
+ // allowed is child node reordering.
+ void basic_plan(InFlow in_flow, uint32_t docid_limit);
+
+ // Similar to basic_plan, but will not reorder children. Note that
+ // this means that flow stats will be misleading as they assume
+ // optimal ordering. Used for testing.
+ void null_plan(InFlow in_flow, uint32_t docid_limit);
+
static Blueprint::UP optimize(Blueprint::UP bp);
- virtual double sort(InFlow in_flow, const Options &opts) = 0;
+ virtual void sort(InFlow in_flow, const Options &opts) = 0;
static Blueprint::UP optimize_and_sort(Blueprint::UP bp, InFlow in_flow, const Options &opts) {
auto result = optimize(std::move(bp));
result->sort(in_flow, opts);
return result;
}
+ static Blueprint::UP optimize_and_sort(Blueprint::UP bp, InFlow in_flow) {
+ return optimize_and_sort(std::move(bp), in_flow, Options::default_options());
+ }
+ static Blueprint::UP optimize_and_sort(Blueprint::UP bp) {
+ return optimize_and_sort(std::move(bp), true, Options::default_options());
+ }
virtual void optimize(Blueprint* &self, OptimizePass pass) = 0;
virtual void optimize_self(OptimizePass pass);
virtual Blueprint::UP get_replacement();
@@ -308,15 +352,15 @@ public:
virtual void freeze() = 0;
bool frozen() const { return _frozen; }
- virtual SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const = 0;
- virtual SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const = 0;
+ virtual SearchIteratorUP createSearch(fef::MatchData &md) const = 0;
+ virtual SearchIteratorUP createFilterSearch(FilterConstraint constraint) const = 0;
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);
- static SearchIteratorUP create_default_filter(bool strict, FilterConstraint constraint);
+ static SearchIteratorUP create_first_child_filter(const Children &children, FilterConstraint constraint);
+ static SearchIteratorUP create_default_filter(FilterConstraint constraint);
// for debug dumping
vespalib::string asString() const;
@@ -406,9 +450,10 @@ public:
~IntermediateBlueprint() override;
void setDocIdLimit(uint32_t limit) noexcept final;
+ void each_node_post_order(const std::function<void(Blueprint&)> &f) override;
void optimize(Blueprint* &self, OptimizePass pass) final;
- double sort(InFlow in_flow, const Options &opts) override;
+ void sort(InFlow in_flow, const Options &opts) override;
void set_global_filter(const GlobalFilter &global_filter, double estimated_hit_ratio) override;
IndexList find(const IPredicate & check) const;
@@ -420,15 +465,13 @@ public:
IntermediateBlueprint &addChild(Blueprint::UP child);
Blueprint::UP removeChild(size_t n);
Blueprint::UP removeLastChild() { return removeChild(childCnt() - 1); }
- SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override;
+ SearchIteratorUP createSearch(fef::MatchData &md) const override;
virtual HitEstimate combine(const std::vector<HitEstimate> &data) const = 0;
virtual FieldSpecBaseList exposeFields() const = 0;
virtual void sort(Children &children, bool strict, bool sort_by_cost) const = 0;
- virtual bool inheritStrict(size_t i) const = 0;
virtual SearchIteratorUP
- createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const = 0;
+ createIntermediateSearch(MultiSearch::Children subSearches, fef::MatchData &md) const = 0;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
void fetchPostings(const ExecuteInfo &execInfo) override;
@@ -445,7 +488,6 @@ private:
State _state;
protected:
void optimize(Blueprint* &self, OptimizePass pass) final;
- double sort(InFlow in_flow, const Options &opts) override;
void setEstimate(HitEstimate est) {
_state.estimate(est);
notifyChange();
@@ -480,11 +522,11 @@ public:
const State &getState() const final { return _state; }
void fetchPostings(const ExecuteInfo &execInfo) override;
void freeze() final;
- SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override;
+ SearchIteratorUP createSearch(fef::MatchData &md) const override;
const LeafBlueprint * asLeaf() const noexcept final { return this; }
virtual bool getRange(vespalib::string & from, vespalib::string & to) const;
- virtual SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const = 0;
+ virtual SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const = 0;
};
// for leaf nodes representing a single term
@@ -492,6 +534,7 @@ struct SimpleLeafBlueprint : LeafBlueprint {
explicit SimpleLeafBlueprint() noexcept : LeafBlueprint(true) {}
explicit SimpleLeafBlueprint(FieldSpecBase field) noexcept : LeafBlueprint(field, true) {}
explicit SimpleLeafBlueprint(FieldSpecBaseList fields) noexcept: LeafBlueprint(std::move(fields), true) {}
+ void sort(InFlow in_flow, const Options &opts) override;
};
// for leaf nodes representing more complex structures like wand/phrase
diff --git a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp
index 7cd00d02bb3..7491215cb59 100644
--- a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.cpp
@@ -39,6 +39,15 @@ DotProductBlueprint::addTerm(Blueprint::UP term, int32_t weight, HitEstimate & e
_terms.push_back(std::move(term));
}
+void
+DotProductBlueprint::sort(InFlow, const Options &opts)
+{
+ strict(true);
+ for (auto &term: _terms) {
+ term->sort(true, opts);
+ }
+}
+
FlowStats
DotProductBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -51,7 +60,7 @@ DotProductBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-DotProductBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool) const
+DotProductBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
assert(getState().numFields() == 1);
@@ -63,16 +72,16 @@ DotProductBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray
assert(childState.numFields() == 1);
childMatch.push_back(childState.field(0).resolve(*md));
// TODO: pass ownership with unique_ptr
- children[i] = _terms[i]->createSearch(*md, true).release();
+ children[i] = _terms[i]->createSearch(*md).release();
}
bool field_is_filter = getState().fields()[0].isFilter();
return DotProductSearch::create(children, *tfmda[0], field_is_filter, childMatch, _weights, std::move(md));
}
SearchIterator::UP
-DotProductBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+DotProductBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_or_filter(_terms, strict, constraint);
+ return create_or_filter(_terms, strict(), constraint);
}
void
diff --git a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h
index ca59f84fce8..370895dd94f 100644
--- a/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/dot_product_blueprint.h
@@ -33,10 +33,11 @@ public:
setEstimate(estimate);
}
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIteratorUP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIteratorUP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
void fetchPostings(const ExecuteInfo &execInfo) override;
diff --git a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp
index 27624abf515..c42f05b64c7 100644
--- a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.cpp
@@ -53,6 +53,17 @@ EquivBlueprint::EquivBlueprint(FieldSpecBaseList fields,
EquivBlueprint::~EquivBlueprint() = default;
+void
+EquivBlueprint::sort(InFlow in_flow, const Options &opts)
+{
+ strict(in_flow.strict());
+ auto flow = OrFlow(in_flow);
+ for (auto &term: _terms) {
+ term->sort(InFlow(flow.strict(), flow.flow()), opts);
+ flow.add(term->estimate());
+ }
+}
+
FlowStats
EquivBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -65,7 +76,7 @@ EquivBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-EquivBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &outputs, bool strict) const
+EquivBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &outputs) const
{
fef::MatchData::UP md = _layout.createMatchData();
MultiSearch::Children children;
@@ -82,15 +93,15 @@ EquivBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &outputs, bo
unpack_needs[child_term_field_match_data->getFieldId()].notify(*child_term_field_match_data);
childMatch.emplace_back(child_term_field_match_data, _exactness[i]);
}
- children.push_back(_terms[i]->createSearch(*md, strict));
+ children.push_back(_terms[i]->createSearch(*md));
}
- return EquivSearch::create(std::move(children), std::move(md), childMatch, outputs, strict);
+ return EquivSearch::create(std::move(children), std::move(md), childMatch, outputs, strict());
}
SearchIterator::UP
-EquivBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+EquivBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_or_filter(_terms, strict, constraint);
+ return create_or_filter(_terms, strict(), constraint);
}
void
diff --git a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.h
index 27e990b3320..147f8269ecd 100644
--- a/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/equiv_blueprint.h
@@ -22,10 +22,11 @@ public:
// used by create visitor
EquivBlueprint& addTerm(Blueprint::UP term, double exactness);
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
void fetchPostings(const ExecuteInfo &execInfo) override;
diff --git a/searchlib/src/vespa/searchlib/queryeval/executeinfo.cpp b/searchlib/src/vespa/searchlib/queryeval/executeinfo.cpp
index c9ec6edb225..9bdc005529d 100644
--- a/searchlib/src/vespa/searchlib/queryeval/executeinfo.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/executeinfo.cpp
@@ -5,16 +5,15 @@
using vespalib::Doom;
namespace search::queryeval {
-const ExecuteInfo ExecuteInfo::TRUE(true, 1.0, Doom::never(), vespalib::ThreadBundle::trivial());
-const ExecuteInfo ExecuteInfo::FALSE(false, 1.0, Doom::never(), vespalib::ThreadBundle::trivial());
+const ExecuteInfo ExecuteInfo::FULL(1.0, Doom::never(), vespalib::ThreadBundle::trivial());
ExecuteInfo::ExecuteInfo() noexcept
- : ExecuteInfo(false, 1.0, Doom::never(), vespalib::ThreadBundle::trivial())
+ : ExecuteInfo(1.0, Doom::never(), vespalib::ThreadBundle::trivial())
{ }
ExecuteInfo
-ExecuteInfo::createForTest(bool strict, double hitRate) noexcept {
- return createForTest(strict, hitRate, Doom::never());
+ExecuteInfo::createForTest(double hitRate) noexcept {
+ return createForTest(hitRate, Doom::never());
}
}
diff --git a/searchlib/src/vespa/searchlib/queryeval/executeinfo.h b/searchlib/src/vespa/searchlib/queryeval/executeinfo.h
index fa2c69e0400..4f9cf8ebdc1 100644
--- a/searchlib/src/vespa/searchlib/queryeval/executeinfo.h
+++ b/searchlib/src/vespa/searchlib/queryeval/executeinfo.h
@@ -14,44 +14,40 @@ namespace search::queryeval {
class ExecuteInfo {
public:
ExecuteInfo() noexcept;
- bool is_strict() const noexcept { return _strict; }
double hit_rate() const noexcept { return _hitRate; }
const vespalib::Doom & doom() const noexcept { return _doom; }
vespalib::ThreadBundle & thread_bundle() const noexcept { return _thread_bundle; }
- static const ExecuteInfo TRUE;
- static const ExecuteInfo FALSE;
- static ExecuteInfo create(bool strict, const ExecuteInfo & org) noexcept {
- return create(strict, org._hitRate, org);
+ static const ExecuteInfo FULL;
+ static ExecuteInfo create(const ExecuteInfo & org) noexcept {
+ return create(org._hitRate, org);
}
- static ExecuteInfo create(bool strict, double hitRate, const ExecuteInfo & org) noexcept {
- return {strict, hitRate, org._doom, org.thread_bundle()};
+ static ExecuteInfo create(double hitRate, const ExecuteInfo & org) noexcept {
+ return {hitRate, org._doom, org.thread_bundle()};
}
- static ExecuteInfo create(bool strict, double hitRate, const vespalib::Doom & doom,
+ static ExecuteInfo create(double hitRate, const vespalib::Doom & doom,
vespalib::ThreadBundle & thread_bundle_in) noexcept
{
- return {strict, hitRate, doom, thread_bundle_in};
+ return {hitRate, doom, thread_bundle_in};
}
- static ExecuteInfo createForTest(bool strict) noexcept {
- return createForTest(strict, 1.0);
+ static ExecuteInfo createForTest() noexcept {
+ return createForTest(1.0);
}
- static ExecuteInfo createForTest(bool strict, double hitRate) noexcept;
- static ExecuteInfo createForTest(bool strict, double hitRate, const vespalib::Doom & doom) noexcept {
- return create(strict, hitRate, doom, vespalib::ThreadBundle::trivial());
+ static ExecuteInfo createForTest(double hitRate) noexcept;
+ static ExecuteInfo createForTest(double hitRate, const vespalib::Doom & doom) noexcept {
+ return create(hitRate, doom, vespalib::ThreadBundle::trivial());
}
private:
- ExecuteInfo(bool strict, double hitRate_in, const vespalib::Doom & doom,
+ ExecuteInfo(double hitRate_in, const vespalib::Doom & doom,
vespalib::ThreadBundle & thread_bundle_in) noexcept
: _doom(doom),
_thread_bundle(thread_bundle_in),
- _hitRate(hitRate_in),
- _strict(strict)
+ _hitRate(hitRate_in)
{ }
const vespalib::Doom _doom;
vespalib::ThreadBundle & _thread_bundle;
double _hitRate;
- bool _strict;
};
}
diff --git a/searchlib/src/vespa/searchlib/queryeval/global_filter.cpp b/searchlib/src/vespa/searchlib/queryeval/global_filter.cpp
index ef00d7a3a75..b3ca97cd053 100644
--- a/searchlib/src/vespa/searchlib/queryeval/global_filter.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/global_filter.cpp
@@ -109,9 +109,8 @@ struct MakePart : Runnable {
bool is_first_thread() const { return (begin == 1); }
bool should_trace(int level) const { return trace && trace->shouldTrace(level); }
void run() override {
- bool strict = true;
auto constraint = Blueprint::FilterConstraint::UPPER_BOUND;
- auto filter = blueprint.createFilterSearch(strict, constraint);
+ auto filter = blueprint.createFilterSearch(constraint);
if (is_first_thread() && should_trace(7)) {
vespalib::slime::ObjectInserter inserter(trace->createCursor("iterator"), "optimized");
filter->asSlime(inserter);
diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
index bc8eaa98541..fb1bb0b6cf1 100644
--- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
@@ -173,20 +173,15 @@ AndNotBlueprint::sort(Children &children, bool strict, bool sort_by_cost) const
}
}
-bool
-AndNotBlueprint::inheritStrict(size_t i) const
-{
- return (i == 0);
-}
-
SearchIterator::UP
AndNotBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData &md) const
+ search::fef::MatchData &md) const
{
UnpackInfo unpack_info(calculateUnpackInfo(md));
if (should_do_termwise_eval(unpack_info, md.get_termwise_limit())) {
TermwiseBlueprintHelper helper(*this, std::move(sub_searches), unpack_info);
- bool termwise_strict = (strict && inheritStrict(helper.first_termwise));
+ bool termwise_strict = ((helper.first_termwise < childCnt()) &&
+ getChild(helper.first_termwise).strict());
auto termwise_search = (helper.first_termwise == 0)
? AndNotSearch::create(helper.get_termwise_children(), termwise_strict)
: OrSearch::create(helper.get_termwise_children(), termwise_strict);
@@ -195,15 +190,15 @@ AndNotBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
if (rearranged.size() == 1) {
return std::move(rearranged[0]);
}
- return AndNotSearch::create(std::move(rearranged), strict);
+ return AndNotSearch::create(std::move(rearranged), strict());
}
- return AndNotSearch::create(std::move(sub_searches), strict);
+ return AndNotSearch::create(std::move(sub_searches), strict());
}
SearchIterator::UP
-AndNotBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+AndNotBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_andnot_filter(get_children(), strict, constraint);
+ return create_andnot_filter(get_children(), strict(), constraint);
}
@@ -271,40 +266,35 @@ AndBlueprint::sort(Children &children, bool strict, bool sort_by_cost) const
}
}
-bool
-AndBlueprint::inheritStrict(size_t i) const
-{
- return (i == 0);
-}
-
SearchIterator::UP
AndBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData & md) const
+ search::fef::MatchData & md) const
{
UnpackInfo unpack_info(calculateUnpackInfo(md));
std::unique_ptr<AndSearch> search;
if (should_do_termwise_eval(unpack_info, md.get_termwise_limit())) {
TermwiseBlueprintHelper helper(*this, std::move(sub_searches), unpack_info);
- bool termwise_strict = (strict && inheritStrict(helper.first_termwise));
+ bool termwise_strict = ((helper.first_termwise < childCnt()) &&
+ getChild(helper.first_termwise).strict());
auto termwise_search = AndSearch::create(helper.get_termwise_children(), termwise_strict);
helper.insert_termwise(std::move(termwise_search), termwise_strict);
auto rearranged = helper.get_result();
if (rearranged.size() == 1) {
return std::move(rearranged[0]);
} else {
- search = AndSearch::create(std::move(rearranged), strict, helper.termwise_unpack);
+ search = AndSearch::create(std::move(rearranged), strict(), helper.termwise_unpack);
}
} else {
- search = AndSearch::create(std::move(sub_searches), strict, unpack_info);
+ search = AndSearch::create(std::move(sub_searches), strict(), unpack_info);
}
search->estimate(getState().estimate().estHits);
return search;
}
SearchIterator::UP
-AndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+AndBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_and_filter(get_children(), strict, constraint);
+ return create_and_filter(get_children(), strict(), constraint);
}
AnyFlow
@@ -376,35 +366,30 @@ OrBlueprint::sort(Children &children, bool strict, bool sort_by_cost) const
}
}
-bool
-OrBlueprint::inheritStrict(size_t) const
-{
- return true;
-}
-
SearchIterator::UP
OrBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData & md) const
+ search::fef::MatchData & md) const
{
UnpackInfo unpack_info(calculateUnpackInfo(md));
if (should_do_termwise_eval(unpack_info, md.get_termwise_limit())) {
TermwiseBlueprintHelper helper(*this, std::move(sub_searches), unpack_info);
- bool termwise_strict = (strict && inheritStrict(helper.first_termwise));
+ bool termwise_strict = ((helper.first_termwise < childCnt()) &&
+ getChild(helper.first_termwise).strict());
auto termwise_search = OrSearch::create(helper.get_termwise_children(), termwise_strict);
helper.insert_termwise(std::move(termwise_search), termwise_strict);
auto rearranged = helper.get_result();
if (rearranged.size() == 1) {
return std::move(rearranged[0]);
}
- return OrSearch::create(std::move(rearranged), strict, helper.termwise_unpack);
+ return OrSearch::create(std::move(rearranged), strict(), helper.termwise_unpack);
}
- return OrSearch::create(std::move(sub_searches), strict, unpack_info);
+ return OrSearch::create(std::move(sub_searches), strict(), unpack_info);
}
SearchIterator::UP
-OrBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+OrBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_or_filter(get_children(), strict, constraint);
+ return create_or_filter(get_children(), strict(), constraint);
}
AnyFlow
@@ -467,12 +452,6 @@ WeakAndBlueprint::sort(Children &, bool, bool) const
}
bool
-WeakAndBlueprint::inheritStrict(size_t) const
-{
- return true;
-}
-
-bool
WeakAndBlueprint::always_needs_unpack() const
{
return true;
@@ -480,7 +459,7 @@ WeakAndBlueprint::always_needs_unpack() const
SearchIterator::UP
WeakAndBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData &) const
+ search::fef::MatchData &) const
{
WeakAndSearch::Terms terms;
assert(sub_searches.size() == childCnt());
@@ -491,13 +470,13 @@ WeakAndBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
_weights[i],
getChild(i).getState().estimate().estHits);
}
- return WeakAndSearch::create(terms, _n, strict);
+ return WeakAndSearch::create(terms, _n, strict());
}
SearchIterator::UP
-WeakAndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+WeakAndBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_or_filter(get_children(), strict, constraint);
+ return create_atmost_or_filter(get_children(), strict(), constraint);
}
//-----------------------------------------------------------------------------
@@ -538,22 +517,16 @@ NearBlueprint::sort(Children &children, bool strict, bool sort_by_cost) const
}
}
-bool
-NearBlueprint::inheritStrict(size_t i) const
-{
- return (i == 0);
-}
-
SearchIterator::UP
-NearBlueprint::createSearch(fef::MatchData &md, bool strict) const
+NearBlueprint::createSearch(fef::MatchData &md) const
{
need_normal_features_for_children(*this, md);
- return IntermediateBlueprint::createSearch(md, strict);
+ return IntermediateBlueprint::createSearch(md);
}
SearchIterator::UP
NearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData &md) const
+ search::fef::MatchData &md) const
{
search::fef::TermFieldMatchDataArray tfmda;
for (size_t i = 0; i < childCnt(); ++i) {
@@ -562,13 +535,13 @@ NearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
tfmda.add(cs.field(j).resolve(md));
}
}
- return SearchIterator::UP(new NearSearch(std::move(sub_searches), tfmda, _window, strict));
+ return SearchIterator::UP(new NearSearch(std::move(sub_searches), tfmda, _window, strict()));
}
SearchIterator::UP
-NearBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+NearBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_and_filter(get_children(), strict, constraint);
+ return create_atmost_and_filter(get_children(), strict(), constraint);
}
//-----------------------------------------------------------------------------
@@ -605,22 +578,16 @@ ONearBlueprint::sort(Children &, bool, bool) const
// ordered near cannot sort children here
}
-bool
-ONearBlueprint::inheritStrict(size_t i) const
-{
- return (i == 0);
-}
-
SearchIterator::UP
-ONearBlueprint::createSearch(fef::MatchData &md, bool strict) const
+ONearBlueprint::createSearch(fef::MatchData &md) const
{
need_normal_features_for_children(*this, md);
- return IntermediateBlueprint::createSearch(md, strict);
+ return IntermediateBlueprint::createSearch(md);
}
SearchIterator::UP
ONearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData &md) const
+ search::fef::MatchData &md) const
{
search::fef::TermFieldMatchDataArray tfmda;
for (size_t i = 0; i < childCnt(); ++i) {
@@ -631,13 +598,13 @@ ONearBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
}
// could sort sub_searches here
// but then strictness inheritance would also need to be fixed
- return SearchIterator::UP(new ONearSearch(std::move(sub_searches), tfmda, _window, strict));
+ return SearchIterator::UP(new ONearSearch(std::move(sub_searches), tfmda, _window, strict()));
}
SearchIterator::UP
-ONearBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+ONearBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_and_filter(get_children(), strict, constraint);
+ return create_atmost_and_filter(get_children(), strict(), constraint);
}
//-----------------------------------------------------------------------------
@@ -696,19 +663,13 @@ RankBlueprint::sort(Children &, bool, bool) const
{
}
-bool
-RankBlueprint::inheritStrict(size_t i) const
-{
- return (i == 0);
-}
-
SearchIterator::UP
RankBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData & md) const
+ search::fef::MatchData & md) const
{
UnpackInfo unpack_info(calculateUnpackInfo(md));
if (unpack_info.unpackAll()) {
- return RankSearch::create(std::move(sub_searches), strict);
+ return RankSearch::create(std::move(sub_searches), strict());
} else {
MultiSearch::Children require_unpack;
require_unpack.reserve(sub_searches.size());
@@ -723,15 +684,15 @@ RankBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
if (require_unpack.size() == 1) {
return std::move(require_unpack[0]);
} else {
- return RankSearch::create(std::move(require_unpack), strict);
+ return RankSearch::create(std::move(require_unpack), strict());
}
}
}
SearchIterator::UP
-RankBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+RankBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_first_child_filter(get_children(), strict, constraint);
+ return create_first_child_filter(get_children(), constraint);
}
AnyFlow
@@ -783,15 +744,9 @@ SourceBlenderBlueprint::sort(Children &, bool, bool) const
{
}
-bool
-SourceBlenderBlueprint::inheritStrict(size_t) const
-{
- return true;
-}
-
SearchIterator::UP
SourceBlenderBlueprint::createIntermediateSearch(MultiSearch::Children sub_searches,
- bool strict, search::fef::MatchData &) const
+ search::fef::MatchData &) const
{
SourceBlenderSearch::Children children;
assert(sub_searches.size() == childCnt());
@@ -800,13 +755,13 @@ SourceBlenderBlueprint::createIntermediateSearch(MultiSearch::Children sub_searc
children.emplace_back(sub_searches[i].release(), getChild(i).getSourceId());
assert(children.back().sourceId != 0xffffffff);
}
- return SourceBlenderSearch::create(_selector.createIterator(), children, strict);
+ return SourceBlenderSearch::create(_selector.createIterator(), children, strict());
}
SearchIterator::UP
-SourceBlenderBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+SourceBlenderBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_or_filter(get_children(), strict, constraint);
+ 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 e0f4be4be06..5d6d098510f 100644
--- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h
+++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h
@@ -22,12 +22,11 @@ public:
AndNotBlueprint * asAndNot() noexcept final { return this; }
Blueprint::UP get_replacement() override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
+ fef::MatchData &md) const override;
SearchIterator::UP
- createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ createFilterSearch(FilterConstraint constraint) const override;
private:
AnyFlow my_flow(InFlow in_flow) const override;
uint8_t calculate_cost_tier() const override {
@@ -50,12 +49,11 @@ public:
AndBlueprint * asAnd() noexcept final { return this; }
Blueprint::UP get_replacement() override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
+ fef::MatchData &md) const override;
SearchIterator::UP
- createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ createFilterSearch(FilterConstraint constraint) const override;
private:
AnyFlow my_flow(InFlow in_flow) const override;
};
@@ -75,12 +73,11 @@ public:
OrBlueprint * asOr() noexcept final { return this; }
Blueprint::UP get_replacement() override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
+ fef::MatchData &md) const override;
SearchIterator::UP
- createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ createFilterSearch(FilterConstraint constraint) const override;
private:
AnyFlow my_flow(InFlow in_flow) const override;
uint8_t calculate_cost_tier() const override;
@@ -100,13 +97,12 @@ public:
HitEstimate combine(const std::vector<HitEstimate> &data) const override;
FieldSpecBaseList exposeFields() const override;
void sort(Children &children, bool strict, bool sort_on_cost) const override;
- bool inheritStrict(size_t i) const override;
bool always_needs_unpack() const override;
WeakAndBlueprint * asWeakAnd() noexcept final { return this; }
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ fef::MatchData &md) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
explicit WeakAndBlueprint(uint32_t n) noexcept : _n(n) {}
~WeakAndBlueprint() override;
@@ -131,12 +127,11 @@ public:
HitEstimate combine(const std::vector<HitEstimate> &data) const override;
FieldSpecBaseList exposeFields() const override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
- SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override;
+ SearchIteratorUP createSearch(fef::MatchData &md) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ fef::MatchData &md) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
explicit NearBlueprint(uint32_t window) noexcept : _window(window) {}
};
@@ -154,12 +149,11 @@ public:
HitEstimate combine(const std::vector<HitEstimate> &data) const override;
FieldSpecBaseList exposeFields() const override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
- SearchIteratorUP createSearch(fef::MatchData &md, bool strict) const override;
+ SearchIteratorUP createSearch(fef::MatchData &md) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ fef::MatchData &md) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
explicit ONearBlueprint(uint32_t window) noexcept : _window(window) {}
};
@@ -175,13 +169,12 @@ public:
void optimize_self(OptimizePass pass) override;
Blueprint::UP get_replacement() override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
bool isRank() const noexcept final { return true; }
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
+ fef::MatchData &md) const override;
SearchIterator::UP
- createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ createFilterSearch(FilterConstraint constraint) const override;
uint8_t calculate_cost_tier() const override {
return (childCnt() > 0) ? get_children()[0]->getState().cost_tier() : State::COST_TIER_NORMAL;
}
@@ -204,12 +197,11 @@ public:
HitEstimate combine(const std::vector<HitEstimate> &data) const override;
FieldSpecBaseList exposeFields() const override;
void sort(Children &children, bool strict, bool sort_by_cost) const override;
- bool inheritStrict(size_t i) const override;
SearchIterator::UP
createIntermediateSearch(MultiSearch::Children subSearches,
- bool strict, fef::MatchData &md) const override;
+ fef::MatchData &md) const override;
SearchIterator::UP
- createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ createFilterSearch(FilterConstraint constraint) const override;
/** check if this blueprint has the same source selector as the other */
bool isCompatibleWith(const SourceBlenderBlueprint &other) const;
diff --git a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp
index b12c2eea404..d825c9e1a20 100644
--- a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp
@@ -17,13 +17,13 @@ EmptyBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-EmptyBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const
+EmptyBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &) const
{
return std::make_unique<EmptySearch>();
}
SearchIterator::UP
-EmptyBlueprint::createFilterSearch(bool /*strict*/, FilterConstraint /* constraint */) const
+EmptyBlueprint::createFilterSearch(FilterConstraint /* constraint */) const
{
return std::make_unique<EmptySearch>();
}
@@ -40,13 +40,13 @@ AlwaysTrueBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-AlwaysTrueBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const
+AlwaysTrueBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &) const
{
return std::make_unique<FullSearch>();
}
SearchIterator::UP
-AlwaysTrueBlueprint::createFilterSearch(bool /*strict*/, FilterConstraint /* constraint */) const
+AlwaysTrueBlueprint::createFilterSearch(FilterConstraint /* constraint */) const
{
return std::make_unique<FullSearch>();
}
@@ -65,19 +65,19 @@ SimpleBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-SimpleBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool strict) const
+SimpleBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &) const
{
- auto search = std::make_unique<SimpleSearch>(_result, strict);
+ auto search = std::make_unique<SimpleSearch>(_result, strict());
search->tag(_tag);
return search;
}
SearchIterator::UP
-SimpleBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+SimpleBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- auto search = std::make_unique<SimpleSearch>(_result, strict);
+ auto search = std::make_unique<SimpleSearch>(_result, strict());
search->tag(_tag +
- (strict ? "<strict," : "<nostrict,") +
+ (strict() ? "<strict," : "<nostrict,") +
(constraint == FilterConstraint::UPPER_BOUND ? "upper>" : "lower>"));
return search;
}
@@ -127,7 +127,7 @@ struct FakeContext : attribute::ISearchContext {
}
attribute::HitEstimate calc_hit_estimate() const override { return attribute::HitEstimate(0); }
std::unique_ptr<SearchIterator> createIterator(fef::TermFieldMatchData *, bool) override { abort(); }
- void fetchPostings(const ExecuteInfo &) override { }
+ void fetchPostings(const ExecuteInfo &, bool) override { }
bool valid() const override { return true; }
Int64Range getAsIntegerTerm() const override { abort(); }
DoubleRange getAsDoubleTerm() const override { abort(); }
@@ -146,7 +146,7 @@ FakeContext::get_committed_docid_limit() const noexcept
}
SearchIterator::UP
-FakeBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool) const
+FakeBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const
{
auto result = std::make_unique<FakeSearch>(_tag, _field.getName(), _term, _result, tfmda);
result->attr_ctx(_ctx.get());
diff --git a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
index d967933fbee..2657c5cf15f 100644
--- a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
+++ b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
@@ -14,24 +14,24 @@ namespace search::queryeval {
class EmptyBlueprint : public SimpleLeafBlueprint
{
protected:
- SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
+ SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const override;
public:
EmptyBlueprint(FieldSpecBaseList fields);
EmptyBlueprint(FieldSpecBase field) : SimpleLeafBlueprint(field) {}
EmptyBlueprint() = default;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
EmptyBlueprint *as_empty() noexcept final override { return this; }
};
class AlwaysTrueBlueprint : public SimpleLeafBlueprint
{
protected:
- SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
+ SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const override;
public:
AlwaysTrueBlueprint();
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
};
//-----------------------------------------------------------------------------
@@ -44,14 +44,14 @@ private:
protected:
SearchIterator::UP
- createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
+ createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const override;
public:
SimpleBlueprint(const SimpleResult &result);
~SimpleBlueprint() override;
SimpleBlueprint &tag(const vespalib::string &tag);
const vespalib::string &tag() const { return _tag; }
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIterator::UP createFilterSearch(FilterConstraint constraint) const override;
};
//-----------------------------------------------------------------------------
@@ -67,7 +67,7 @@ private:
protected:
SearchIterator::UP
- createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
+ createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
public:
FakeBlueprint(const FieldSpec &field, const FakeResult &result);
@@ -95,8 +95,8 @@ public:
return default_flow_stats(docid_limit, _result.inspect().size(), 0);
}
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
};
diff --git a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.cpp
index 8ab258ef58e..faa4b65e3b0 100644
--- a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.cpp
@@ -125,8 +125,14 @@ NearestNeighborBlueprint::perform_top_k(const search::tensor::NearestNeighborInd
}
}
+void
+NearestNeighborBlueprint::sort(InFlow in_flow, const Options &)
+{
+ strict(in_flow.strict());
+}
+
std::unique_ptr<SearchIterator>
-NearestNeighborBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray& tfmda, bool strict) const
+NearestNeighborBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray& tfmda) const
{
assert(tfmda.size() == 1);
fef::TermFieldMatchData &tfmd = *tfmda[0]; // always search in only one field
@@ -137,7 +143,7 @@ NearestNeighborBlueprint::createLeafSearch(const search::fef::TermFieldMatchData
default:
;
}
- return NearestNeighborIterator::create(strict, tfmd,
+ return NearestNeighborIterator::create(strict(), tfmd,
std::make_unique<search::tensor::DistanceCalculator>(_attr_tensor, _query_tensor),
_distance_heap, *_global_filter);
}
diff --git a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.h
index 73608b8172b..864ae6c2d47 100644
--- a/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/nearest_neighbor_blueprint.h
@@ -69,14 +69,14 @@ public:
Algorithm get_algorithm() const { return _algorithm; }
double get_distance_threshold() const { return _distance_threshold; }
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override {
return default_flow_stats(docid_limit, getState().estimate().estHits, 0);
}
- std::unique_ptr<SearchIterator> createLeafSearch(const search::fef::TermFieldMatchDataArray& tfmda,
- bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ std::unique_ptr<SearchIterator> createLeafSearch(const search::fef::TermFieldMatchDataArray& tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
void visitMembers(vespalib::ObjectVisitor& visitor) const override;
bool always_needs_unpack() const override;
diff --git a/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.cpp
index 6dd4b241830..48d2e957252 100644
--- a/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.cpp
@@ -279,8 +279,14 @@ PredicateBlueprint::fetchPostings(const ExecuteInfo &) {
}
}
+void
+PredicateBlueprint::sort(InFlow in_flow, const Options &)
+{
+ strict(in_flow.strict());
+}
+
SearchIterator::UP
-PredicateBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool) const {
+PredicateBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const {
const auto &attribute = predicate_attribute();
PredicateAttribute::MinFeatureHandle mfh = attribute.getMinFeatureVector();
auto interval_range_vector = attribute.getIntervalRangeVector();
diff --git a/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.h
index d9c432b38bd..5cba0f1b949 100644
--- a/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/predicate_blueprint.h
@@ -49,15 +49,16 @@ public:
~PredicateBlueprint();
void fetchPostings(const ExecuteInfo &execInfo) override;
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t) const override {
return default_flow_stats(_interval_btree_iterators.size() + _interval_vector_iterators.size() +
_bounds_btree_iterators.size() + _bounds_vector_iterators.size() + 2);
}
SearchIterator::UP
- createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override {
- return create_default_filter(strict, constraint);
+ createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override {
+ return create_default_filter(constraint);
}
// Exposed for testing
diff --git a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp
index 628020cfea2..7ba4bfc5711 100644
--- a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.cpp
@@ -44,6 +44,17 @@ SameElementBlueprint::addTerm(Blueprint::UP term)
_terms.push_back(std::move(term));
}
+void
+SameElementBlueprint::sort(InFlow in_flow, const Options &opts)
+{
+ strict(in_flow.strict());
+ auto flow = AndFlow(in_flow);
+ for (auto &term: _terms) {
+ term->sort(InFlow(flow.strict(), flow.flow()), opts);
+ flow.add(term->estimate());
+ }
+}
+
FlowStats
SameElementBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -75,19 +86,19 @@ SameElementBlueprint::fetchPostings(const ExecuteInfo &execInfo)
double hit_rate = execInfo.hit_rate() * _terms[0]->estimate();
for (size_t i = 1; i < _terms.size(); ++i) {
Blueprint & term = *_terms[i];
- term.fetchPostings(ExecuteInfo::create(false, hit_rate, execInfo));
+ term.fetchPostings(ExecuteInfo::create(hit_rate, execInfo));
hit_rate = hit_rate * _terms[i]->estimate();
}
}
std::unique_ptr<SameElementSearch>
-SameElementBlueprint::create_same_element_search(search::fef::TermFieldMatchData& tfmd, bool strict) const
+SameElementBlueprint::create_same_element_search(search::fef::TermFieldMatchData& tfmd) const
{
fef::MatchData::UP md = _layout.createMatchData();
std::vector<ElementIterator::UP> children(_terms.size());
for (size_t i = 0; i < _terms.size(); ++i) {
const State &childState = _terms[i]->getState();
- SearchIterator::UP child = _terms[i]->createSearch(*md, (strict && (i == 0)));
+ SearchIterator::UP child = _terms[i]->createSearch(*md);
const attribute::ISearchContext *context = _terms[i]->get_attribute_search_context();
if (context == nullptr) {
children[i] = std::make_unique<ElementIteratorWrapper>(std::move(child), *childState.field(0).resolve(*md));
@@ -95,20 +106,20 @@ SameElementBlueprint::create_same_element_search(search::fef::TermFieldMatchData
children[i] = std::make_unique<attribute::SearchContextElementIterator>(std::move(child), *context);
}
}
- return std::make_unique<SameElementSearch>(tfmd, std::move(md), std::move(children), strict);
+ return std::make_unique<SameElementSearch>(tfmd, std::move(md), std::move(children), strict());
}
SearchIterator::UP
-SameElementBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const
+SameElementBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
- return create_same_element_search(*tfmda[0], strict);
+ return create_same_element_search(*tfmda[0]);
}
SearchIterator::UP
-SameElementBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+SameElementBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_and_filter(_terms, strict, constraint);
+ return create_atmost_and_filter(_terms, strict(), constraint);
}
void
diff --git a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h
index 279a5f7d654..61e2a85d5e2 100644
--- a/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/same_element_blueprint.h
@@ -34,15 +34,15 @@ public:
// used by create visitor
void addTerm(Blueprint::UP term);
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
void optimize_self(OptimizePass pass) override;
void fetchPostings(const ExecuteInfo &execInfo) override;
- std::unique_ptr<SameElementSearch> create_same_element_search(search::fef::TermFieldMatchData& tfmd, bool strict) const;
- SearchIteratorUP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda,
- bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ std::unique_ptr<SameElementSearch> create_same_element_search(search::fef::TermFieldMatchData& tfmd) const;
+ SearchIteratorUP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
const std::vector<Blueprint::UP> &terms() const { return _terms; }
const vespalib::string &field_name() const { return _field_name; }
diff --git a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp
index 953e7350074..0867a072c3b 100644
--- a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.cpp
@@ -45,6 +45,15 @@ SimplePhraseBlueprint::addTerm(Blueprint::UP term)
_terms.push_back(std::move(term));
}
+void
+SimplePhraseBlueprint::sort(InFlow in_flow, const Options &opts)
+{
+ strict(in_flow.strict());
+ for (auto &term: _terms) {
+ term->sort(in_flow, opts);
+ }
+}
+
FlowStats
SimplePhraseBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -58,7 +67,7 @@ SimplePhraseBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-SimplePhraseBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const
+SimplePhraseBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
fef::MatchData::UP md = _layout.createMatchData();
@@ -73,24 +82,23 @@ SimplePhraseBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmd
child_term_field_match_data->setNeedInterleavedFeatures(tfmda[0]->needs_interleaved_features());
child_term_field_match_data->setNeedNormalFeatures(true);
childMatch.add(child_term_field_match_data);
- children.push_back(_terms[i]->createSearch(*md, strict));
+ children.push_back(_terms[i]->createSearch(*md));
order_map.insert(std::make_pair(childState.estimate().estHits, i));
}
std::vector<uint32_t> eval_order;
eval_order.reserve(order_map.size());
for (const auto & child : order_map) {
eval_order.push_back(child.second);
- }
-
+ }
return std::make_unique<SimplePhraseSearch>(std::move(children),
std::move(md), std::move(childMatch),
- std::move(eval_order), *tfmda[0], strict);
+ std::move(eval_order), *tfmda[0], strict());
}
SearchIterator::UP
-SimplePhraseBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+SimplePhraseBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_and_filter(_terms, strict, constraint);
+ 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 da7ec9c9b36..14717742c30 100644
--- a/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/simple_phrase_blueprint.h
@@ -30,10 +30,11 @@ public:
// used by create visitor
void addTerm(Blueprint::UP term);
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
void fetchPostings(const ExecuteInfo &execInfo) override;
};
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 78fe3882aab..e85649a3758 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
@@ -66,6 +66,17 @@ ParallelWeakAndBlueprint::addTerm(Blueprint::UP term, int32_t weight, HitEstimat
_terms.push_back(std::move(term));
}
+void
+ParallelWeakAndBlueprint::sort(InFlow in_flow, const Options &opts)
+{
+ strict(in_flow.strict());
+ auto flow = OrFlow(in_flow);
+ for (auto &term: _terms) {
+ term->sort(InFlow(flow.strict(), flow.flow()), opts);
+ flow.add(term->estimate());
+ }
+}
+
FlowStats
ParallelWeakAndBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -80,7 +91,7 @@ ParallelWeakAndBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-ParallelWeakAndBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const
+ParallelWeakAndBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
fef::MatchData::UP childrenMatchData = _layout.createMatchData();
@@ -90,7 +101,7 @@ ParallelWeakAndBlueprint::createLeafSearch(const search::fef::TermFieldMatchData
const State &childState = _terms[i]->getState();
assert(childState.numFields() == 1);
// TODO: pass ownership with unique_ptr
- terms.emplace_back(_terms[i]->createSearch(*childrenMatchData, true).release(),
+ terms.emplace_back(_terms[i]->createSearch(*childrenMatchData).release(),
_weights[i],
childState.estimate().estHits,
childState.field(0).resolve(*childrenMatchData));
@@ -102,13 +113,13 @@ ParallelWeakAndBlueprint::createLeafSearch(const search::fef::TermFieldMatchData
_thresholdBoostFactor,
_scoresAdjustFrequency).setDocIdLimit(get_docid_limit()),
ParallelWeakAndSearch::RankParams(*tfmda[0],
- std::move(childrenMatchData)), strict));
+ std::move(childrenMatchData)), strict()));
}
std::unique_ptr<SearchIterator>
-ParallelWeakAndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+ParallelWeakAndBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_atmost_or_filter(_terms, strict, constraint);
+ 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 ade64577c80..22f8ee1bf6f 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
@@ -62,10 +62,11 @@ public:
set_tree_size(_terms.size() + 1);
}
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- std::unique_ptr<SearchIterator> createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIterator::UP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ std::unique_ptr<SearchIterator> createFilterSearch(FilterConstraint constraint) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
void fetchPostings(const ExecuteInfo &execInfo) override;
bool always_needs_unpack() const override;
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 8bf2dd53470..8f4f8d50c43 100644
--- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.cpp
@@ -34,7 +34,7 @@ WeightedSetTermMatchingElementsSearch::WeightedSetTermMatchingElementsSearch(con
_search()
{
_tfmda.add(&_tfmd);
- _search.reset(static_cast<WeightedSetTermSearch *>(bp.createLeafSearch(_tfmda, false).release()));
+ _search.reset(static_cast<WeightedSetTermSearch *>(bp.createLeafSearch(_tfmda).release()));
}
@@ -93,6 +93,15 @@ WeightedSetTermBlueprint::addTerm(Blueprint::UP term, int32_t weight, HitEstimat
_terms.push_back(std::move(term));
}
+void
+WeightedSetTermBlueprint::sort(InFlow, const Options &opts)
+{
+ strict(true);
+ for (auto &term: _terms) {
+ term->sort(true, opts);
+ }
+}
+
FlowStats
WeightedSetTermBlueprint::calculate_flow_stats(uint32_t docid_limit) const
{
@@ -105,14 +114,14 @@ WeightedSetTermBlueprint::calculate_flow_stats(uint32_t docid_limit) const
}
SearchIterator::UP
-WeightedSetTermBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool) const
+WeightedSetTermBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const
{
assert(tfmda.size() == 1);
if ((_terms.size() == 1) && tfmda[0]->isNotNeeded()) {
if (const LeafBlueprint * leaf = _terms[0]->asLeaf(); leaf != nullptr) {
// Always returnin a strict iterator independently of what was required,
// as that is what we do with all the children when there are more.
- return leaf->createLeafSearch(tfmda, true);
+ return leaf->createLeafSearch(tfmda);
}
}
fef::MatchData::UP md = _layout.createMatchData();
@@ -120,15 +129,15 @@ WeightedSetTermBlueprint::createLeafSearch(const fef::TermFieldMatchDataArray &t
children.reserve(_terms.size());
for (const auto & _term : _terms) {
// TODO: pass ownership with unique_ptr
- children.push_back(_term->createSearch(*md, true).release());
+ children.push_back(_term->createSearch(*md).release());
}
return WeightedSetTermSearch::create(children, *tfmda[0], _children_field.isFilter(), _weights, std::move(md));
}
SearchIterator::UP
-WeightedSetTermBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const
+WeightedSetTermBlueprint::createFilterSearch(FilterConstraint constraint) const
{
- return create_or_filter(_terms, strict, constraint);
+ return create_or_filter(_terms, strict(), constraint);
}
std::unique_ptr<MatchingElementsSearch>
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 240b2a47eb3..47deff058a0 100644
--- a/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/weighted_set_term_blueprint.h
@@ -35,10 +35,11 @@ public:
setEstimate(estimate);
}
+ void sort(InFlow in_flow, const Options &opts) override;
FlowStats calculate_flow_stats(uint32_t docid_limit) const override;
- SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda, bool strict) const override;
- SearchIteratorUP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ SearchIteratorUP createLeafSearch(const fef::TermFieldMatchDataArray &tfmda) const override;
+ SearchIteratorUP createFilterSearch(FilterConstraint constraint) const override;
std::unique_ptr<MatchingElementsSearch> create_matching_elements_search(const MatchingElementsFields &fields) const override;
void visitMembers(vespalib::ObjectVisitor &visitor) const override;
private: