diff options
author | Arne H Juul <arnej27959@users.noreply.github.com> | 2021-10-19 18:29:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-19 18:29:53 +0200 |
commit | 8964cbed0c69e539235eb482651e6f84efd22898 (patch) | |
tree | 0652f770ca7a165035aaee67853c8456fe0cd71a | |
parent | e722ea4cb24548558a5a0b50ae483cce0bd3f31c (diff) | |
parent | 5bac27daa62f5b9136695a319a7ff5a7b8bcb602 (diff) |
Merge pull request #19622 from vespa-engine/arnej/add-true-and-false-itemsv7.486.17
add ITEM_TRUE and ITEM_FALSE query nodes
35 files changed, 246 insertions, 9 deletions
diff --git a/searchcore/src/tests/proton/matching/query_test.cpp b/searchcore/src/tests/proton/matching/query_test.cpp index 432a17392e5..a09437be46b 100644 --- a/searchcore/src/tests/proton/matching/query_test.cpp +++ b/searchcore/src/tests/proton/matching/query_test.cpp @@ -120,6 +120,7 @@ class Test : public vespalib::TestApp { void requireThatSameElementTermsAreProperlyPrefixed(); void requireThatSameElementDoesNotAllocateMatchData(); void requireThatSameElementIteratorsCanBeBuilt(); + void requireThatConstBoolBlueprintsAreCreatedCorrectly(); public: ~Test() override; @@ -1088,6 +1089,28 @@ Test::requireThatSameElementIteratorsCanBeBuilt() { EXPECT_TRUE(iterator->seek(8)); } +void Test::requireThatConstBoolBlueprintsAreCreatedCorrectly() { + using search::queryeval::AlwaysTrueBlueprint; + using search::queryeval::EmptyBlueprint; + + ProtonTrue true_node; + ProtonFalse false_node; + + FakeRequestContext requestContext; + FakeSearchContext context; + context.setLimit(1000); + context.addIdx(0).idx(0).getFake() + .addResult(field, "foo", FakeResult().doc(1).doc(3)); + + Blueprint::UP t_blueprint = BlueprintBuilder::build(requestContext, true_node, context); + auto *tbp = dynamic_cast<AlwaysTrueBlueprint*>(t_blueprint.get()); + EXPECT_TRUE(tbp != nullptr); + + Blueprint::UP f_blueprint = BlueprintBuilder::build(requestContext, false_node, context); + auto *fbp = dynamic_cast<EmptyBlueprint*>(f_blueprint.get()); + EXPECT_TRUE(fbp != nullptr); +} + Test::~Test() = default; int @@ -1126,6 +1149,7 @@ Test::Main() TEST_CALL(requireThatSameElementTermsAreProperlyPrefixed); TEST_CALL(requireThatSameElementDoesNotAllocateMatchData); TEST_CALL(requireThatSameElementIteratorsCanBeBuilt); + TEST_CALL(requireThatConstBoolBlueprintsAreCreatedCorrectly); TEST_DONE(); } diff --git a/searchcore/src/tests/proton/matching/unpacking_iterators_optimizer/unpacking_iterators_optimizer_test.cpp b/searchcore/src/tests/proton/matching/unpacking_iterators_optimizer/unpacking_iterators_optimizer_test.cpp index 5dc9808a5b6..ffd08b3bbef 100644 --- a/searchcore/src/tests/proton/matching/unpacking_iterators_optimizer/unpacking_iterators_optimizer_test.cpp +++ b/searchcore/src/tests/proton/matching/unpacking_iterators_optimizer/unpacking_iterators_optimizer_test.cpp @@ -67,6 +67,8 @@ struct DumpQuery : QueryVisitor { void visit(PredicateQuery &) override {} void visit(RegExpTerm &) override {} void visit(NearestNeighborTerm &) override {} + void visit(TrueQueryNode &) override {} + void visit(FalseQueryNode &) override {} }; std::string dump_query(Node &root) { diff --git a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp index 0d640f2a599..9be5920c0ed 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp @@ -144,7 +144,6 @@ protected: void visit(ProtonONear &n) override { buildIntermediate(new ONearBlueprint(n.getDistance()), n); } void visit(ProtonSameElement &n) override { buildSameElement(n); } - void visit(ProtonWeightedSetTerm &n) override { buildTerm(n); } void visit(ProtonDotProduct &n) override { buildTerm(n); } void visit(ProtonWandTerm &n) override { buildTerm(n); } @@ -160,6 +159,12 @@ protected: void visit(ProtonPredicateQuery &n) override { buildTerm(n); } void visit(ProtonRegExpTerm &n) override { buildTerm(n); } void visit(ProtonNearestNeighborTerm &n) override { buildTerm(n); } + void visit(ProtonTrue &) override { + _result = std::make_unique<AlwaysTrueBlueprint>(); + } + void visit(ProtonFalse &) override { + _result = std::make_unique<EmptyBlueprint>(); + } public: BlueprintBuilderVisitor(const IRequestContext & requestContext, ISearchContext &context) : diff --git a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h index 2ebd52d7fa7..e7817dcecd2 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h +++ b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h @@ -114,7 +114,8 @@ typedef search::query::SimpleOr ProtonOr; typedef search::query::SimpleRank ProtonRank; typedef search::query::SimpleWeakAnd ProtonWeakAnd; typedef search::query::SimpleSameElement ProtonSameElement; - +typedef search::query::SimpleTrue ProtonTrue; +typedef search::query::SimpleFalse ProtonFalse; struct ProtonEquiv final : public ProtonTermBase<search::query::Equiv> { search::fef::MatchDataLayout children_mdl; @@ -161,6 +162,8 @@ struct ProtonNodeTypes { typedef ProtonPredicateQuery PredicateQuery; typedef ProtonRegExpTerm RegExpTerm; typedef ProtonNearestNeighborTerm NearestNeighborTerm; + typedef ProtonTrue TrueQueryNode; + typedef ProtonFalse FalseQueryNode; }; } diff --git a/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp index a3722c1e3b9..34cb5369c1e 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp @@ -51,7 +51,6 @@ public: void visit(ProtonRank &) override {} void visit(ProtonWeakAnd &) override {} void visit(ProtonSameElement &) override {} - void visit(ProtonWeightedSetTerm &) override {} void visit(ProtonDotProduct &) override {} void visit(ProtonWandTerm &) override {} @@ -68,6 +67,8 @@ public: void visit(ProtonPredicateQuery &) override {} void visit(ProtonRegExpTerm &n) override { visitTerm(n); } void visit(ProtonNearestNeighborTerm &) override {} + void visit(ProtonTrue &) override {} + void visit(ProtonFalse &) override {} }; } // namespace proton::matching::<unnamed> diff --git a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp index 08ec0e767db..c2abeaa36ee 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp @@ -26,6 +26,8 @@ struct TermDataFromTermVisitor void visit(ProtonRank &) override {} void visit(ProtonWeakAnd &) override {} void visit(ProtonSameElement &) override { } + void visit(ProtonTrue &) override {} + void visit(ProtonFalse &) override {} void visit(ProtonWeightedSetTerm &n) override { visitTerm(n); } void visit(ProtonDotProduct &n) override { visitTerm(n); } diff --git a/searchcore/src/vespa/searchcore/proton/matching/unpacking_iterators_optimizer.cpp b/searchcore/src/vespa/searchcore/proton/matching/unpacking_iterators_optimizer.cpp index eada88010dd..d60bc53aa57 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/unpacking_iterators_optimizer.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/unpacking_iterators_optimizer.cpp @@ -57,6 +57,9 @@ struct TermExpander : QueryVisitor { void visit(PredicateQuery &) override {} void visit(RegExpTerm &) override {} void visit(NearestNeighborTerm &) override {} + void visit(TrueQueryNode &) override {} + void visit(FalseQueryNode &) override {} + void flush(Intermediate &parent) { for (Node::UP &term: terms) { parent.append(std::move(term)); diff --git a/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp b/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp index 5de0a8cb69d..5592215f9e2 100644 --- a/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp +++ b/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp @@ -188,6 +188,8 @@ private: void visit(Near &) override { } void visit(ONear &) override { } void visit(SameElement &) override { } + void visit(TrueQueryNode &) override {} + void visit(FalseQueryNode &) override {} void visit(WeightedSetTerm &n) override { visitTerm(n); } void visit(DotProduct &n) override { visitTerm(n); } diff --git a/searchlib/src/tests/query/customtypevisitor_test.cpp b/searchlib/src/tests/query/customtypevisitor_test.cpp index 747b376777a..35280fb0bd8 100644 --- a/searchlib/src/tests/query/customtypevisitor_test.cpp +++ b/searchlib/src/tests/query/customtypevisitor_test.cpp @@ -42,7 +42,11 @@ struct MyDotProduct : DotProduct { MyDotProduct() : DotProduct(0, "view", 0, Wei struct MyWandTerm : WandTerm { MyWandTerm() : WandTerm(0, "view", 0, Weight(42), 57, 67, 77.7) {} }; struct MyPredicateQuery : InitTerm<PredicateQuery> {}; struct MyRegExpTerm : InitTerm<RegExpTerm> {}; -struct MyNearestNeighborTerm : NearestNeighborTerm {}; +struct MyNearestNeighborTerm : NearestNeighborTerm { + MyNearestNeighborTerm() : NearestNeighborTerm("qt", "fn", 0, Weight(42), 10, true, 666, 1234.5) {} +}; +struct MyTrue : TrueQueryNode {}; +struct MyFalse : FalseQueryNode {}; struct MyQueryNodeTypes { typedef MyAnd And; @@ -68,6 +72,8 @@ struct MyQueryNodeTypes { typedef MyPredicateQuery PredicateQuery; typedef MyRegExpTerm RegExpTerm; typedef MyNearestNeighborTerm NearestNeighborTerm; + typedef MyFalse FalseQueryNode; + typedef MyTrue TrueQueryNode; }; class MyCustomVisitor : public CustomTypeVisitor<MyQueryNodeTypes> @@ -104,6 +110,8 @@ public: void visit(MyPredicateQuery &) override { setVisited<MyPredicateQuery>(); } void visit(MyRegExpTerm &) override { setVisited<MyRegExpTerm>(); } void visit(MyNearestNeighborTerm &) override { setVisited<MyNearestNeighborTerm>(); } + void visit(MyTrue &) override { setVisited<MyTrue>(); } + void visit(MyFalse &) override { setVisited<MyFalse>(); } }; template <class T> @@ -136,7 +144,11 @@ TEST("customtypevisitor_test") { requireThatNodeIsVisited<MyWandTerm>(); requireThatNodeIsVisited<MyPredicateQuery>(); requireThatNodeIsVisited<MyRegExpTerm>(); + requireThatNodeIsVisited<MyLocationTerm>(); + requireThatNodeIsVisited<MyNearestNeighborTerm>(); + requireThatNodeIsVisited<MyTrue>(); + requireThatNodeIsVisited<MyFalse>(); } } // namespace -TEST_MAIN() { TEST_RUN_ALL(); }
\ No newline at end of file +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/tests/query/query_visitor_test.cpp b/searchlib/src/tests/query/query_visitor_test.cpp index 9090575bd44..9f73c1ff585 100644 --- a/searchlib/src/tests/query/query_visitor_test.cpp +++ b/searchlib/src/tests/query/query_visitor_test.cpp @@ -47,6 +47,8 @@ public: void visit(PredicateQuery &) override { isVisited<PredicateQuery>() = true; } void visit(RegExpTerm &) override { isVisited<RegExpTerm>() = true; } void visit(NearestNeighborTerm &) override { isVisited<NearestNeighborTerm>() = true; } + void visit(TrueQueryNode &) override { isVisited<TrueQueryNode>() = true; } + void visit(FalseQueryNode &) override { isVisited<FalseQueryNode>() = true; } }; template <class T> @@ -81,6 +83,8 @@ TEST("requireThatAllNodesCanBeVisited") { checkVisit<PredicateQuery>(new SimplePredicateQuery(PredicateQueryTerm::UP(), "field", 0, Weight(0))); checkVisit<RegExpTerm>(new SimpleRegExpTerm("t", "field", 0, Weight(0))); checkVisit<NearestNeighborTerm>(new SimpleNearestNeighborTerm("query_tensor", "doc_tensor", 0, Weight(0), 123, true, 321, 100100.25)); + checkVisit<TrueQueryNode>(new SimpleTrue()); + checkVisit<FalseQueryNode>(new SimpleFalse()); } } // namespace diff --git a/searchlib/src/tests/query/querybuilder_test.cpp b/searchlib/src/tests/query/querybuilder_test.cpp index 0c784287e5c..93cfad27742 100644 --- a/searchlib/src/tests/query/querybuilder_test.cpp +++ b/searchlib/src/tests/query/querybuilder_test.cpp @@ -47,7 +47,7 @@ PredicateQueryTerm::UP getPredicateQueryTerm() { template <class NodeTypes> Node::UP createQueryTree() { QueryBuilder<NodeTypes> builder; - builder.addAnd(11); + builder.addAnd(12); { builder.addRank(2); { @@ -110,6 +110,11 @@ Node::UP createQueryTree() { builder.addStringTerm(str[6], view[6], id[6], weight[7]); } builder.add_nearest_neighbor_term("query_tensor", "doc_tensor", id[3], weight[5], 7, true, 33, 100100.25); + builder.addAndNot(2); + { + builder.add_true_node(); + builder.add_false_node(); + } } Node::UP node = builder.build(); ASSERT_TRUE(node.get()); @@ -172,10 +177,12 @@ void checkQueryTreeTypes(Node *node) { typedef typename NodeTypes::WeakAnd WeakAnd; typedef typename NodeTypes::PredicateQuery PredicateQuery; typedef typename NodeTypes::RegExpTerm RegExpTerm; + typedef typename NodeTypes::TrueQueryNode TrueNode; + typedef typename NodeTypes::FalseQueryNode FalseNode; ASSERT_TRUE(node); auto* and_node = as_node<And>(node); - EXPECT_EQUAL(11u, and_node->getChildren().size()); + EXPECT_EQUAL(12u, and_node->getChildren().size()); auto* rank = as_node<Rank>(and_node->getChildren()[0]); EXPECT_EQUAL(2u, rank->getChildren().size()); @@ -292,6 +299,13 @@ void checkQueryTreeTypes(Node *node) { EXPECT_EQUAL(id[3], nearest_neighbor->getId()); EXPECT_EQUAL(weight[5].percent(), nearest_neighbor->getWeight().percent()); EXPECT_EQUAL(7u, nearest_neighbor->get_target_num_hits()); + + and_not = as_node<AndNot>(and_node->getChildren()[11]); + EXPECT_EQUAL(2u, and_not->getChildren().size()); + auto* true_node = as_node<TrueNode>(and_not->getChildren()[0]); + auto* false_node = as_node<FalseNode>(and_not->getChildren()[1]); + EXPECT_TRUE(true_node); + EXPECT_TRUE(false_node); } struct AbstractTypes { @@ -316,6 +330,8 @@ struct AbstractTypes { typedef search::query::WeakAnd WeakAnd; typedef search::query::PredicateQuery PredicateQuery; typedef search::query::RegExpTerm RegExpTerm; + typedef search::query::TrueQueryNode TrueQueryNode; + typedef search::query::FalseQueryNode FalseQueryNode; }; // Builds a tree with simplequery and checks that the results have the @@ -409,6 +425,8 @@ struct MyNearestNeighborTerm : NearestNeighborTerm { : NearestNeighborTerm(query_tensor_name, field_name, i, w, target_num_hits, allow_approximate, explore_additional_hits, distance_threshold) {} }; +struct MyTrue : TrueQueryNode {}; +struct MyFalse : FalseQueryNode {}; struct MyQueryNodeTypes { typedef MyAnd And; @@ -434,6 +452,8 @@ struct MyQueryNodeTypes { typedef MyPredicateQuery PredicateQuery; typedef MyRegExpTerm RegExpTerm; typedef MyNearestNeighborTerm NearestNeighborTerm; + typedef MyTrue TrueQueryNode; + typedef MyFalse FalseQueryNode; }; TEST("require that Custom Query Trees Can Be Built") { diff --git a/searchlib/src/vespa/searchlib/parsequery/parse.h b/searchlib/src/vespa/searchlib/parsequery/parse.h index 7b9fd610ee5..7db9f0e43ea 100644 --- a/searchlib/src/vespa/searchlib/parsequery/parse.h +++ b/searchlib/src/vespa/searchlib/parsequery/parse.h @@ -53,8 +53,10 @@ public: ITEM_REGEXP = 24, ITEM_WORD_ALTERNATIVES = 25, ITEM_NEAREST_NEIGHBOR = 26, - ITEM_GEO_LOCATION_TERM = 27, - ITEM_MAX = 28, // Indicates how long tables must be. + ITEM_GEO_LOCATION_TERM = 27, + ITEM_TRUE = 28, + ITEM_FALSE = 29, + ITEM_MAX = 30, // Indicates how long tables must be. ITEM_UNDEF = 31, }; diff --git a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp index 2ec392e0078..aa13c93810a 100644 --- a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp +++ b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp @@ -187,6 +187,10 @@ bool SimpleQueryStackDumpIterator::readNext() { case ParseItem::ITEM_NEAREST_NEIGHBOR: if ( ! readNN(p)) return false; break; + case ParseItem::ITEM_TRUE: + case ParseItem::ITEM_FALSE: + // no content + break; default: // Unknown item, so report that no more are available return false; diff --git a/searchlib/src/vespa/searchlib/query/streaming/query.cpp b/searchlib/src/vespa/searchlib/query/streaming/query.cpp index 4773827c036..309edf4d472 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/query.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/query.cpp @@ -126,6 +126,10 @@ TrueNode::evaluate() const return true; } +bool FalseNode::evaluate() const { + return false; +} + bool AndQueryNode::evaluate() const { diff --git a/searchlib/src/vespa/searchlib/query/streaming/query.h b/searchlib/src/vespa/searchlib/query/streaming/query.h index 75388d564ee..d77bb7f0f65 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/query.h +++ b/searchlib/src/vespa/searchlib/query/streaming/query.h @@ -49,6 +49,14 @@ public: bool evaluate() const override; }; +/** False operator. Matches nothing. */ +class FalseNode : public QueryConnector +{ +public: + FalseNode() : QueryConnector("AND") { } + bool evaluate() const override; +}; + /** N-ary Or operator that simply ANDs all the nodes together. */ diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index 38939e3a8a4..060573861d9 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -64,6 +64,12 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor } } break; + case ParseItem::ITEM_TRUE: + qn = std::make_unique<TrueNode>(); + break; + case ParseItem::ITEM_FALSE: + qn = std::make_unique<FalseNode>(); + break; case ParseItem::ITEM_GEO_LOCATION_TERM: // TODO implement this: // vespalib::string field = queryRep.getIndexName(); diff --git a/searchlib/src/vespa/searchlib/query/tree/CMakeLists.txt b/searchlib/src/vespa/searchlib/query/tree/CMakeLists.txt index ef2003e4ae1..ec9156fbb52 100644 --- a/searchlib/src/vespa/searchlib/query/tree/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/query/tree/CMakeLists.txt @@ -1,6 +1,7 @@ # Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. vespa_add_library(searchlib_query_tree OBJECT SOURCES + const_bool_nodes.cpp intermediate.cpp intermediatenodes.cpp querybuilder.cpp diff --git a/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.cpp b/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.cpp new file mode 100644 index 00000000000..78d8c69a1b5 --- /dev/null +++ b/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.cpp @@ -0,0 +1,10 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "const_bool_nodes.h" + +namespace search::query { + +TrueQueryNode::~TrueQueryNode() = default; +FalseQueryNode::~FalseQueryNode() = default; + +} diff --git a/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.h b/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.h new file mode 100644 index 00000000000..fd31f3bf8f2 --- /dev/null +++ b/searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.h @@ -0,0 +1,21 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include "node.h" +#include "queryvisitor.h" + +namespace search::query { + +class TrueQueryNode : public Node { +public: + ~TrueQueryNode(); + void accept(QueryVisitor &visitor) override { visitor.visit(*this); } +}; + +class FalseQueryNode : public Node { +public: + ~FalseQueryNode(); + void accept(QueryVisitor &visitor) override { visitor.visit(*this); } +}; + +} diff --git a/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h b/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h index de4ae416504..bf92f0ae04c 100644 --- a/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h @@ -28,6 +28,10 @@ private: void visit(typename NodeTypes::WeakAnd &n) override { visitChildren(n); } void visit(typename NodeTypes::SameElement &n) override { visitChildren(n); } + // leaf nodes without terms: + void visit(typename NodeTypes::TrueQueryNode &) override {} + void visit(typename NodeTypes::FalseQueryNode &) override {} + // phrases and weighted set terms are conceptual leaf nodes and // should be handled that way. }; diff --git a/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h b/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h index aa4408d0dbe..9f29c34aa05 100644 --- a/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h @@ -50,6 +50,8 @@ public: virtual void visit(typename NodeTypes::PredicateQuery &) = 0; virtual void visit(typename NodeTypes::RegExpTerm &) = 0; virtual void visit(typename NodeTypes::NearestNeighborTerm &) = 0; + virtual void visit(typename NodeTypes::TrueQueryNode &) = 0; + virtual void visit(typename NodeTypes::FalseQueryNode &) = 0; private: // Route QueryVisit requests to the correct custom type. @@ -77,6 +79,8 @@ private: typedef typename NodeTypes::PredicateQuery TPredicateQuery; typedef typename NodeTypes::RegExpTerm TRegExpTerm; typedef typename NodeTypes::NearestNeighborTerm TNearestNeighborTerm; + typedef typename NodeTypes::TrueQueryNode TTrueQueryNode; + typedef typename NodeTypes::FalseQueryNode TFalseQueryNode; void visit(And &n) override { visit(static_cast<TAnd&>(n)); } void visit(AndNot &n) override { visit(static_cast<TAndNot&>(n)); } @@ -101,6 +105,8 @@ private: void visit(PredicateQuery &n) override { visit(static_cast<TPredicateQuery&>(n)); } void visit(RegExpTerm &n) override { visit(static_cast<TRegExpTerm&>(n)); } void visit(NearestNeighborTerm &n) override { visit(static_cast<TNearestNeighborTerm&>(n)); } + void visit(TrueQueryNode &n) override { visit(static_cast<TTrueQueryNode&>(n)); } + void visit(FalseQueryNode &n) override { visit(static_cast<TFalseQueryNode&>(n)); } }; } diff --git a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h index a0788f0a777..9631e2afded 100644 --- a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h +++ b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h @@ -21,6 +21,7 @@ #include "predicate_query_term.h" #include "node.h" +#include "const_bool_nodes.h" #include <vespa/searchlib/query/weight.h> #include <stack> @@ -98,6 +99,12 @@ public: // You may specialize these functions for your own traits class to have full // control of the query node instantiation. +template <class NodeTypes> +typename NodeTypes::TrueQueryNode *create_true() { return new typename NodeTypes::TrueQueryNode; } + +template <class NodeTypes> +typename NodeTypes::FalseQueryNode *create_false() { return new typename NodeTypes::FalseQueryNode; } + // Intermediate nodes template <class NodeTypes> typename NodeTypes::And *createAnd() { return new typename NodeTypes::And; } @@ -328,6 +335,12 @@ public: adjustWeight(weight); return addTerm(create_nearest_neighbor_term<NodeTypes>(query_tensor_name, field_name, id, weight, target_num_hits, allow_approximate, explore_additional_hits, distance_threshold)); } + typename NodeTypes::TrueQueryNode &add_true_node() { + return addTerm(create_true<NodeTypes>()); + } + typename NodeTypes::FalseQueryNode &add_false_node() { + return addTerm(create_false<NodeTypes>()); + } }; } diff --git a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h index 7501cd2c6f2..3fb72f93b23 100644 --- a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h +++ b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h @@ -185,6 +185,14 @@ private: node.get_allow_approximate(), node.get_explore_additional_hits(), node.get_distance_threshold())); } + + void visit(TrueQueryNode &) override { + _builder.add_true_node(); + } + + void visit(FalseQueryNode &) override { + _builder.add_false_node(); + } }; } diff --git a/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h b/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h index 3d53c1181ed..02887975085 100644 --- a/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h @@ -27,6 +27,8 @@ class PredicateQuery; class RegExpTerm; class SameElement; class NearestNeighborTerm; +class TrueQueryNode; +class FalseQueryNode; struct QueryVisitor { virtual ~QueryVisitor() {} @@ -54,6 +56,8 @@ struct QueryVisitor { virtual void visit(PredicateQuery &) = 0; virtual void visit(RegExpTerm &) = 0; virtual void visit(NearestNeighborTerm &) = 0; + virtual void visit(TrueQueryNode &) = 0; + virtual void visit(FalseQueryNode &) = 0; }; } diff --git a/searchlib/src/vespa/searchlib/query/tree/simplequery.h b/searchlib/src/vespa/searchlib/query/tree/simplequery.h index 44d869bc8bf..0e52698c915 100644 --- a/searchlib/src/vespa/searchlib/query/tree/simplequery.h +++ b/searchlib/src/vespa/searchlib/query/tree/simplequery.h @@ -7,11 +7,14 @@ #pragma once +#include "const_bool_nodes.h" #include "intermediatenodes.h" #include "termnodes.h" namespace search::query { +struct SimpleTrue : TrueQueryNode {}; +struct SimpleFalse : FalseQueryNode {}; struct SimpleAnd : And {}; struct SimpleAndNot : AndNot {}; struct SimpleNear : Near { SimpleNear(size_t dist) : Near(dist) {} }; @@ -119,6 +122,8 @@ struct SimpleQueryNodeTypes { using And = SimpleAnd; using AndNot = SimpleAndNot; using Equiv = SimpleEquiv; + using TrueQueryNode = SimpleTrue; + using FalseQueryNode = SimpleFalse; using NumberTerm = SimpleNumberTerm; using LocationTerm = SimpleLocationTerm; using Near = SimpleNear; diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp index 4b89a7f9425..d45a72d316a 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp @@ -242,6 +242,14 @@ class QueryNodeConverter : public QueryVisitor { createTerm(node, ParseItem::ITEM_GEO_LOCATION_TERM); } + void visit(TrueQueryNode &) override { + appendByte(ParseItem::ITEM_TRUE); + } + + void visit(FalseQueryNode &) override { + appendByte(ParseItem::ITEM_FALSE); + } + void visit(PrefixTerm &node) override { createTerm(node, ParseItem::ITEM_PREFIXTERM); } diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h index f8254186900..5a6f315205e 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h @@ -153,6 +153,10 @@ private: builder.add_nearest_neighbor_term(query_tensor_name, field_name, id, weight, target_num_hits, allow_approximate, explore_additional_hits, distance_threshold); + } else if (type == ParseItem::ITEM_TRUE) { + builder.add_true_node(); + } else if (type == ParseItem::ITEM_FALSE) { + builder.add_false_node(); } else { vespalib::stringref term = queryStack.getTerm(); vespalib::stringref view = queryStack.getIndexName(); diff --git a/searchlib/src/vespa/searchlib/query/tree/termnodes.h b/searchlib/src/vespa/searchlib/query/tree/termnodes.h index 51667de9530..a728b674999 100644 --- a/searchlib/src/vespa/searchlib/query/tree/termnodes.h +++ b/searchlib/src/vespa/searchlib/query/tree/termnodes.h @@ -7,6 +7,7 @@ #include "querynodemixin.h" #include "range.h" #include "term.h" +#include "const_bool_nodes.h" namespace search::query { diff --git a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp index e1322d04081..5b8757411bd 100644 --- a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp @@ -90,4 +90,12 @@ CreateBlueprintVisitorHelper::visitWandTerm(query::WandTerm &n) { n); } +void CreateBlueprintVisitorHelper::visit(query::TrueQueryNode &) { + setResult(std::make_unique<AlwaysTrueBlueprint>()); +} + +void CreateBlueprintVisitorHelper::visit(query::FalseQueryNode &) { + setResult(std::make_unique<EmptyBlueprint>()); +} + } diff --git a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h index ceca605b2e6..86cde64a197 100644 --- a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h +++ b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h @@ -73,6 +73,9 @@ public: void visit(query::SuffixTerm &n) override = 0; void visit(query::RegExpTerm &n) override = 0; void visit(query::NearestNeighborTerm &n) override = 0; + + void visit(query::TrueQueryNode &) final override; + void visit(query::FalseQueryNode &) final override; }; } diff --git a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp index a72fbc8d57a..53ffe839a72 100644 --- a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp @@ -2,6 +2,7 @@ #include "leaf_blueprints.h" #include "emptysearch.h" +#include "full_search.h" #include "simplesearch.h" #include "fake_search.h" @@ -37,6 +38,24 @@ EmptyBlueprint::EmptyBlueprint() { } + +SearchIterator::UP +AlwaysTrueBlueprint::createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const +{ + return std::make_unique<FullSearch>(); +} + +SearchIterator::UP +AlwaysTrueBlueprint::createFilterSearch(bool /*strict*/, FilterConstraint /* constraint */) const +{ + return std::make_unique<FullSearch>(); +} + +AlwaysTrueBlueprint::AlwaysTrueBlueprint() : SimpleLeafBlueprint(FieldSpecBaseList()) +{ + setEstimate(HitEstimate(search::endDocId, false)); +} + //----------------------------------------------------------------------------- SearchIterator::UP diff --git a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h index 288f4dec1c8..7a1d8f3d253 100644 --- a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h +++ b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h @@ -22,6 +22,15 @@ public: SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; }; +class AlwaysTrueBlueprint : public SimpleLeafBlueprint +{ +protected: + SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &tfmda, bool strict) const override; +public: + AlwaysTrueBlueprint(); + SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; +}; + //----------------------------------------------------------------------------- class SimpleBlueprint : public SimpleLeafBlueprint diff --git a/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp b/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp index bcf3fb8e86d..08c0280ee68 100644 --- a/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp @@ -16,6 +16,7 @@ using search::query::And; using search::query::AndNot; using search::query::DotProduct; using search::query::Equiv; +using search::query::FalseQueryNode; using search::query::LocationTerm; using search::query::Near; using search::query::NearestNeighborTerm; @@ -34,6 +35,7 @@ using search::query::SameElement; using search::query::StringTerm; using search::query::SubstringTerm; using search::query::SuffixTerm; +using search::query::TrueQueryNode; using search::query::WandTerm; using search::query::WeakAnd; using search::query::WeightedSetTerm; @@ -105,6 +107,8 @@ struct TermAsStringVisitor : public QueryVisitor { void visit(RegExpTerm &n) override {visitTerm(n); } void visit(PredicateQuery &) override {illegalVisit(); } void visit(NearestNeighborTerm &) override { illegalVisit(); } + void visit(TrueQueryNode &) override { illegalVisit(); } + void visit(FalseQueryNode &) override { illegalVisit(); } }; void throwFailure(const search::query::Node &term_node) __attribute((noinline)); diff --git a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp index f821684dc8c..c28446cf01f 100644 --- a/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp +++ b/searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp @@ -163,6 +163,10 @@ SimpleQueryStackItem::AppendBuffer(RawBuf *buf) const buf->appendCompressedPositiveNumber(termLen); buf->append(_term.c_str(), termLen); break; + case ITEM_TRUE: + case ITEM_FALSE: + // no content + break; case ITEM_PURE_WEIGHTED_STRING: buf->appendCompressedPositiveNumber(termLen); buf->append(_term.c_str(), termLen); diff --git a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp index 5869de27b1d..79957217267 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp @@ -249,6 +249,9 @@ JuniperQueryAdapter::Traverse(juniper::IQueryVisitor *v) const if (!v->VisitWITHIN(&item, iterator.getArity(),iterator.getNearDistance())) rc = SkipItem(&iterator); break; + case search::ParseItem::ITEM_TRUE: + case search::ParseItem::ITEM_FALSE: + break; // Unhandled items are just ignored by juniper case search::ParseItem::ITEM_WAND: case search::ParseItem::ITEM_WEIGHTED_SET: |