aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne H Juul <arnej27959@users.noreply.github.com>2021-10-19 18:29:53 +0200
committerGitHub <noreply@github.com>2021-10-19 18:29:53 +0200
commit8964cbed0c69e539235eb482651e6f84efd22898 (patch)
tree0652f770ca7a165035aaee67853c8456fe0cd71a
parente722ea4cb24548558a5a0b50ae483cce0bd3f31c (diff)
parent5bac27daa62f5b9136695a319a7ff5a7b8bcb602 (diff)
Merge pull request #19622 from vespa-engine/arnej/add-true-and-false-itemsv7.486.17
add ITEM_TRUE and ITEM_FALSE query nodes
-rw-r--r--searchcore/src/tests/proton/matching/query_test.cpp24
-rw-r--r--searchcore/src/tests/proton/matching/unpacking_iterators_optimizer/unpacking_iterators_optimizer_test.cpp2
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp7
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/querynodes.h5
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/same_element_builder.cpp3
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp2
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/unpacking_iterators_optimizer.cpp3
-rw-r--r--searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp2
-rw-r--r--searchlib/src/tests/query/customtypevisitor_test.cpp16
-rw-r--r--searchlib/src/tests/query/query_visitor_test.cpp4
-rw-r--r--searchlib/src/tests/query/querybuilder_test.cpp24
-rw-r--r--searchlib/src/vespa/searchlib/parsequery/parse.h6
-rw-r--r--searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/query/streaming/query.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/query/streaming/query.h8
-rw-r--r--searchlib/src/vespa/searchlib/query/streaming/querynode.cpp6
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.cpp10
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/const_bool_nodes.h21
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h4
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h6
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/querybuilder.h13
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/queryreplicator.h8
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/queryvisitor.h4
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/simplequery.h5
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h4
-rw-r--r--searchlib/src/vespa/searchlib/query/tree/termnodes.h1
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp8
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h3
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.cpp19
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h9
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/termasstring.cpp4
-rw-r--r--searchsummary/src/tests/extractkeywords/simplequerystackitem.cpp4
-rw-r--r--searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp3
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: