diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2021-04-22 14:11:31 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2021-04-22 14:19:17 +0000 |
commit | 77d585e79ed10d687ca50db4c731c285e80f833b (patch) | |
tree | 16a35a5d666a3eb3dfe7c4f405b2c90189d534f1 /searchlib | |
parent | 7bb93176d1c15704f89d69fa6daaaefdb19692c9 (diff) |
- Prevent the rewrite that happens with equiv and phrase to handle floating point queries in string fields, from happening in under a same-element node.
- Add raw stackdump from previously failing query.
Diffstat (limited to 'searchlib')
3 files changed, 35 insertions, 4 deletions
diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index 5ce34cfcc3f..21d55b485c0 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -708,6 +708,24 @@ TEST("require that we do not break the stack on bad query") { EXPECT_FALSE(term.isValid()); } +TEST("a unhandled sameElement stack") { + const char * stack = "\022\002\026xyz_abcdefghij_xyzxyzxQ\001\vxxxxxx_name\034xxxxxx_xxxx_xxxxxxx_xxxxxxxxE\002\005delta\b<0.00393"; + vespalib::stringref stackDump(stack); + EXPECT_EQUAL(85u, stackDump.size()); + AllowRewrite empty; + const Query q(empty, stackDump); + EXPECT_TRUE(q.valid()); + const QueryNode & root = q.getRoot(); + auto sameElement = dynamic_cast<const SameElementQueryNode *>(&root); + EXPECT_TRUE(sameElement != nullptr); + EXPECT_EQUAL(2u, sameElement->size()); + EXPECT_EQUAL("xyz_abcdefghij_xyzxyzx", sameElement->getIndex()); + auto term0 = dynamic_cast<const QueryTerm *>((*sameElement)[0].get()); + EXPECT_TRUE(term0 != nullptr); + auto term1 = dynamic_cast<const QueryTerm *>((*sameElement)[1].get()); + EXPECT_TRUE(term1 != nullptr); +} + namespace { void verifyQueryTermNode(const vespalib::string & index, const QueryNode *node) { EXPECT_TRUE(dynamic_cast<const QueryTerm *>(node) != nullptr); diff --git a/searchlib/src/vespa/searchlib/query/streaming/query.cpp b/searchlib/src/vespa/searchlib/query/streaming/query.cpp index bec1bdfc8ae..c6b5ba45d9a 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/query.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/query.cpp @@ -2,6 +2,7 @@ #include "query.h" #include <vespa/searchlib/parsequery/stackdumpiterator.h> #include <vespa/vespalib/objects/visit.hpp> +#include <cassert> namespace search::streaming { @@ -155,6 +156,11 @@ bool SameElementQueryNode::evaluate() const { const HitList & SameElementQueryNode::evaluateHits(HitList & hl) const { + // TODO This should have been done in a different way, but there are currently no way for that. + // Sanity check should be cheap enough that it does not matter. + for (const auto & child : *this) { + assert(dynamic_cast<const QueryTerm *>(child.get()) != nullptr); + } hl.clear(); if ( !AndQueryNode::evaluate()) return hl; diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index cabc9b6dae4..906e2bf4a34 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -10,8 +10,10 @@ namespace search::streaming { namespace { vespalib::stringref DEFAULT("default"); - bool isPhraseOrNear(const QueryNode * qn) { - return dynamic_cast<const NearQueryNode *> (qn) || dynamic_cast<const PhraseQueryNode *> (qn); + bool disableRewrite(const QueryNode * qn) { + return dynamic_cast<const NearQueryNode *> (qn) || + dynamic_cast<const PhraseQueryNode *> (qn) || + dynamic_cast<const SameElementQueryNode *>(qn); } } @@ -56,7 +58,7 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor if (qc->isFlattenable(queryRep.getType())) { arity += queryRep.getArity(); } else { - UP child = Build(qc, factory, queryRep, allowRewrite && !isPhraseOrNear(qn.get())); + UP child = Build(qc, factory, queryRep, allowRewrite && !disableRewrite(qn.get())); qc->push_back(std::move(child)); } } @@ -128,7 +130,12 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor auto qt = std::make_unique<QueryTerm>(factory.create(), ssTerm, ssIndex, sTerm); qt->setWeight(queryRep.GetWeight()); qt->setUniqueId(queryRep.getUniqueId()); - if ( qt->encoding().isBase10Integer() || ! qt->encoding().isFloat() || ! factory.getRewriteFloatTerms() || !allowRewrite || (ssTerm.find('.') == vespalib::string::npos)) { + if (qt->encoding().isBase10Integer() || + ! qt->encoding().isFloat() || + ! factory.getRewriteFloatTerms() || + ! allowRewrite || + (ssTerm.find('.') == vespalib::string::npos)) + { qn = std::move(qt); } else { auto phrase = std::make_unique<PhraseQueryNode>(); |