summaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa
diff options
context:
space:
mode:
Diffstat (limited to 'searchlib/src/vespa')
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.cpp5
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/blueprint.h7
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp28
-rw-r--r--searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h1
4 files changed, 27 insertions, 14 deletions
diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
index a8e2e77623f..639805e116e 100644
--- a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp
@@ -36,8 +36,8 @@ void maybe_eliminate_self(Blueprint* &self, Blueprint::UP replacement) {
self->setSourceId(discard->getSourceId());
discard->setParent(nullptr);
}
- // replace with empty blueprint if empty
- if (self->getState().estimate().empty) {
+ // replace with empty blueprint if empty, skip if already empty blueprint
+ if ((self->as_empty() == nullptr) && self->getState().estimate().empty) {
Blueprint::UP discard(self);
self = new EmptyBlueprint(discard->getState().fields());
self->setParent(discard->getParent());
@@ -130,7 +130,6 @@ Blueprint::UP
Blueprint::optimize(Blueprint::UP bp) {
Blueprint *root = bp.release();
root->optimize(root, OptimizePass::FIRST);
- root->optimize(root, OptimizePass::SECOND);
root->optimize(root, OptimizePass::LAST);
return Blueprint::UP(root);
}
diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h
index 81d225661d0..a02cb7dd17f 100644
--- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h
+++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h
@@ -32,6 +32,7 @@ class SourceBlenderBlueprint;
class AndBlueprint;
class AndNotBlueprint;
class OrBlueprint;
+class EmptyBlueprint;
/**
* A Blueprint is an intermediate representation of a search. More
@@ -50,7 +51,7 @@ public:
using Children = std::vector<Blueprint::UP>;
using SearchIteratorUP = std::unique_ptr<SearchIterator>;
- enum class OptimizePass { FIRST, SECOND, LAST };
+ enum class OptimizePass { FIRST, LAST };
struct HitEstimate {
uint32_t estHits;
@@ -270,6 +271,9 @@ public:
virtual bool isRank() const noexcept { return false; }
virtual const attribute::ISearchContext *get_attribute_search_context() const noexcept { return nullptr; }
+ // to avoid replacing an empty blueprint with another empty blueprint
+ virtual EmptyBlueprint *as_empty() noexcept { return nullptr; }
+
// For document summaries with matched-elements-only set.
virtual std::unique_ptr<MatchingElementsSearch> create_matching_elements_search(const MatchingElementsFields &fields) const;
};
@@ -347,6 +351,7 @@ public:
IntermediateBlueprint & insertChild(size_t n, Blueprint::UP child);
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;
virtual HitEstimate combine(const std::vector<HitEstimate> &data) const = 0;
diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
index b315965b5f4..4d0656b421c 100644
--- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
+++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp
@@ -52,7 +52,7 @@ void optimize_source_blenders(IntermediateBlueprint &self, size_t begin_idx) {
source_blenders.pop_back();
SourceBlenderBlueprint * blender = blender_up->asSourceBlender();
while (blender->childCnt() > 0) {
- Blueprint::UP child_up = blender->removeChild(blender->childCnt() - 1);
+ Blueprint::UP child_up = blender->removeLastChild();
size_t source_idx = lookup_create_source(sources, child_up->getSourceId(), self.get_docid_limit());
sources[source_idx]->addChild(std::move(child_up));
}
@@ -107,14 +107,24 @@ AndNotBlueprint::optimize_self(OptimizePass pass)
return;
}
if (pass == OptimizePass::FIRST) {
- AndNotBlueprint * child = getChild(0).asAndNot();
- if (child != nullptr) {
+ if (auto *child = getChild(0).asAndNot()) {
while (child->childCnt() > 1) {
- addChild(child->removeChild(1));
+ addChild(child->removeLastChild());
}
insertChild(1, child->removeChild(0));
removeChild(0);
}
+ if (auto *child = getChild(0).asAnd()) {
+ for (size_t i = 0; i < child->childCnt(); ++i) {
+ if (auto *grand_child = child->getChild(i).asAndNot()) {
+ while (grand_child->childCnt() > 1) {
+ addChild(grand_child->removeLastChild());
+ }
+ child->addChild(grand_child->removeChild(0));
+ child->removeChild(i--);
+ }
+ }
+ }
for (size_t i = 1; i < childCnt(); ++i) {
if (getChild(i).getState().estimate().empty) {
removeChild(i--);
@@ -195,10 +205,9 @@ AndBlueprint::optimize_self(OptimizePass pass)
{
if (pass == OptimizePass::FIRST) {
for (size_t i = 0; i < childCnt(); ++i) {
- AndBlueprint * child = getChild(i).asAnd();
- if (child != nullptr) {
+ if (auto *child = getChild(i).asAnd()) {
while (child->childCnt() > 0) {
- addChild(child->removeChild(0));
+ addChild(child->removeLastChild());
}
removeChild(i--);
}
@@ -297,10 +306,9 @@ OrBlueprint::optimize_self(OptimizePass pass)
{
if (pass == OptimizePass::FIRST) {
for (size_t i = 0; (childCnt() > 1) && (i < childCnt()); ++i) {
- OrBlueprint * child = getChild(i).asOr();
- if (child != nullptr) {
+ if (auto *child = getChild(i).asOr()) {
while (child->childCnt() > 0) {
- addChild(child->removeChild(0));
+ addChild(child->removeLastChild());
}
removeChild(i--);
} else if (getChild(i).getState().estimate().empty) {
diff --git a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
index a95ca0efc72..a1c23649dd6 100644
--- a/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
+++ b/searchlib/src/vespa/searchlib/queryeval/leaf_blueprints.h
@@ -20,6 +20,7 @@ public:
EmptyBlueprint(FieldSpecBase field) : SimpleLeafBlueprint(field) {}
EmptyBlueprint() = default;
SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override;
+ EmptyBlueprint *as_empty() noexcept final override { return this; }
};
class AlwaysTrueBlueprint : public SimpleLeafBlueprint