diff options
23 files changed, 341 insertions, 319 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json index 363ab3918d3..b4bf45d655a 100644 --- a/config-model-api/abi-spec.json +++ b/config-model-api/abi-spec.json @@ -1280,9 +1280,7 @@ "public java.util.List ignoredHttpUserAgents()", "public boolean enableProxyProtocolMixedMode()", "public java.lang.String logFileCompressionAlgorithm(java.lang.String)", - "public boolean enableGlobalPhase()", "public java.lang.String summaryDecodePolicy()", - "public boolean enableNestedMultivalueGrouping()", "public int contentLayerMetadataFeatureLevel()", "public boolean dynamicHeapSize()", "public java.lang.String unknownConfigDefinition()", @@ -1459,9 +1457,7 @@ ], "methods" : [ "public abstract long aggregatedModelCostInBytes()", - "public void registerModel(com.yahoo.config.application.api.ApplicationFile)", "public abstract void registerModel(com.yahoo.config.application.api.ApplicationFile, com.yahoo.config.model.api.OnnxModelOptions)", - "public void registerModel(java.net.URI)", "public abstract void registerModel(java.net.URI, com.yahoo.config.model.api.OnnxModelOptions)", "public abstract java.util.Map models()", "public abstract void setRestartOnDeploy()", diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java index 4ee7b00b79f..31ef1e75acd 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java @@ -106,9 +106,7 @@ public interface ModelContext { @ModelFeatureFlag(owners = {"arnej", "andreer"}) default List<String> ignoredHttpUserAgents() { return List.of(); } @ModelFeatureFlag(owners = {"tokle"}) default boolean enableProxyProtocolMixedMode() { return true; } @ModelFeatureFlag(owners = {"arnej"}) default String logFileCompressionAlgorithm(String defVal) { return defVal; } - @ModelFeatureFlag(owners = {"arnej, bjorncs"}, removeAfter = "8.262") default boolean enableGlobalPhase() { return true; } @ModelFeatureFlag(owners = {"baldersheim"}, comment = "Select summary decode type") default String summaryDecodePolicy() { return "eager"; } - @ModelFeatureFlag(owners = {"baldersheim"}, removeAfter = "8.261") default boolean enableNestedMultivalueGrouping() { return true; } @ModelFeatureFlag(owners = {"vekterli"}) default int contentLayerMetadataFeatureLevel() { return 0; } @ModelFeatureFlag(owners = {"bjorncs"}) default boolean dynamicHeapSize() { return false; } @ModelFeatureFlag(owners = {"hmusum"}) default String unknownConfigDefinition() { return "warn"; } diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/OnnxModelCost.java b/config-model-api/src/main/java/com/yahoo/config/model/api/OnnxModelCost.java index 69f2b6b6dce..17a0d64aac9 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/OnnxModelCost.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/OnnxModelCost.java @@ -18,15 +18,7 @@ public interface OnnxModelCost { interface Calculator { long aggregatedModelCostInBytes(); - // TODO: Unused, remove when 8.263.7 is oldest model in use - default void registerModel(ApplicationFile path) { - registerModel(path, OnnxModelOptions.empty()); - } void registerModel(ApplicationFile path, OnnxModelOptions onnxModelOptions); - // TODO: Unused, remove when 8.263.7 is oldest model in use - default void registerModel(URI uri) { - registerModel(uri, OnnxModelOptions.empty()); - } void registerModel(URI uri, OnnxModelOptions onnxModelOptions); Map<String, ModelInfo> models(); void setRestartOnDeploy(); diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 2e1c661e09a..6f0254145d6 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -141,7 +141,6 @@ public class TestProperties implements ModelContext.Properties, ModelContext.Fea @Override public String summaryDecodePolicy() { return summaryDecodePolicy; } @Override public Optional<CloudAccount> cloudAccount() { return cloudAccount; } @Override public boolean allowUserFilters() { return allowUserFilters; } - @Override public boolean enableGlobalPhase() { return true; } // Enable global-phase by default for unit tests only @Override public List<DataplaneToken> dataplaneTokens() { return dataplaneTokens; } @Override public int contentLayerMetadataFeatureLevel() { return contentLayerMetadataFeatureLevel; } @Override public boolean dynamicHeapSize() { return dynamicHeapSize; } diff --git a/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java b/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java index ca2a00ffe46..9fca0bb0ddb 100644 --- a/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java +++ b/container-core/src/main/java/com/yahoo/processing/request/ErrorMessage.java @@ -160,7 +160,7 @@ public class ErrorMessage implements Cloneable { message = getMessage(t); if (message == null) continue; if (lastMessage != null && lastMessage.equals(message)) continue; - if (b.length() > 0) + if (!b.isEmpty()) b.append(": "); b.append(message); } @@ -191,9 +191,7 @@ public class ErrorMessage implements Cloneable { */ @Override public boolean equals(Object o) { - if (!(o instanceof ErrorMessage)) return false; - - ErrorMessage other = (ErrorMessage) o; + if (!(o instanceof ErrorMessage other)) return false; if (this.code != other.code) return false; diff --git a/container-search/abi-spec.json b/container-search/abi-spec.json index 80833e3e27c..aedccbee46b 100644 --- a/container-search/abi-spec.json +++ b/container-search/abi-spec.json @@ -7802,6 +7802,7 @@ "public static com.yahoo.search.result.ErrorMessage createNotFound(java.lang.String)", "public static com.yahoo.search.result.ErrorMessage createBadRequest(java.lang.String)", "public static com.yahoo.search.result.ErrorMessage createInternalServerError(java.lang.String)", + "public static com.yahoo.search.result.ErrorMessage createInternalServerError(java.lang.String, java.lang.Throwable)", "public static com.yahoo.search.result.ErrorMessage createSearchReplyError(java.lang.String)", "public static com.yahoo.search.result.ErrorMessage createDocsumReplyError(java.lang.String)", "public void setSource(java.lang.String)", diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java index e20c4271fe0..441c4326355 100644 --- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java @@ -270,7 +270,12 @@ public class ClusterSearcher extends Searcher { Result result = task.get(); mergedResult.mergeWith(result); mergedResult.hits().addAll(result.hits().asUnorderedHits()); - } catch (ExecutionException | InterruptedException e) { + } catch (ExecutionException e) { + mergedResult.hits().addError(ErrorMessage.createInternalServerError("Failed querying '" + + query.getModel().getRestrict() + "': " + + Exceptions.toMessageString(e), + e)); + } catch (InterruptedException e) { mergedResult.hits().addError(ErrorMessage.createInternalServerError("Failed querying '" + query.getModel().getRestrict() + "': " + Exceptions.toMessageString(e))); diff --git a/container-search/src/main/java/com/yahoo/search/result/ErrorMessage.java b/container-search/src/main/java/com/yahoo/search/result/ErrorMessage.java index a6f57aa866a..503bbd725c3 100644 --- a/container-search/src/main/java/com/yahoo/search/result/ErrorMessage.java +++ b/container-search/src/main/java/com/yahoo/search/result/ErrorMessage.java @@ -163,6 +163,14 @@ public class ErrorMessage extends com.yahoo.processing.request.ErrorMessage { return new ErrorMessage(INTERNAL_SERVER_ERROR.code, "Internal server error.", detailedMessage); } + /** + * Creates an error analog to HTTP internal server error. If this error is present, a + * HTTP layer will return 500. + */ + public static ErrorMessage createInternalServerError(String detailedMessage, Throwable cause) { + return new ErrorMessage(INTERNAL_SERVER_ERROR.code, "Internal server error.", detailedMessage, cause); + } + /** Wraps an error message received in a SearchReply packet */ public static ErrorMessage createSearchReplyError(String detailedMessage) { return new ErrorMessage(RESULT_HAS_ERRORS.code, "Error in search reply.", detailedMessage); diff --git a/dependency-versions/pom.xml b/dependency-versions/pom.xml index 4c7f26430ea..7768fdcc52d 100644 --- a/dependency-versions/pom.xml +++ b/dependency-versions/pom.xml @@ -114,7 +114,6 @@ <junit.vespa.version>5.10.0</junit.vespa.version> <junit.platform.vespa.version>1.10.0</junit.platform.vespa.version> <junit4.vespa.version>4.13.2</junit4.vespa.version> - <logback.vespa.version>1.2.13</logback.vespa.version> <luben.zstd.vespa.version>1.5.5-11</luben.zstd.vespa.version> <lucene.vespa.version>9.9.1</lucene.vespa.version> <maven-archiver.vespa.version>3.6.1</maven-archiver.vespa.version> diff --git a/parent/pom.xml b/parent/pom.xml index 6cc2902136b..3fc520c86c7 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -460,16 +460,6 @@ <version>${huggingface.vespa.version}</version> </dependency> <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - <version>${logback.vespa.version}</version> - </dependency> - <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-core</artifactId> - <version>${logback.vespa.version}</version> - </dependency> - <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-core</artifactId> <version>${aws-sdk.vespa.version}</version> @@ -504,6 +494,14 @@ <artifactId>zookeeper</artifactId> <version>${zookeeper.client.vespa.version}</version> <exclusions> + <!-- + Container provides wiring for all common log libraries + Duplicate embedding results in various warnings being printed to stderr + --> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>*</artifactId> + </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index 08705fa837b..f5370785167 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -38,7 +38,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 7); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7); EXPECT_EQ(db, 7); } @@ -48,15 +48,24 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, -7); } + { + QueryTerm q(factory.create(), "+7", "index", TermType::WORD); + EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); + EXPECT_EQ(ia, 7); + EXPECT_EQ(ib, 7); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, 7); + EXPECT_EQ(db, 7); + } { QueryTerm q(factory.create(), "7.5", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7.5); EXPECT_EQ(db, 7.5); } @@ -64,7 +73,7 @@ TEST(StreamingQueryTest, test_query_language) { QueryTerm q(factory.create(), "-7.5", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7.5); EXPECT_EQ(db, -7.5); } @@ -74,8 +83,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits<double>::max()); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, -std::numeric_limits<double>::infinity()); EXPECT_LT(db, 7); EXPECT_GT(db, 6.99); } @@ -85,8 +94,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits<double>::max()); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, -std::numeric_limits<double>::infinity()); EXPECT_EQ(db, 7); } @@ -95,10 +104,10 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 8); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, 7); EXPECT_LT(da, 7.01); - EXPECT_EQ(db, std::numeric_limits<double>::max()); + EXPECT_EQ(db, std::numeric_limits<double>::infinity()); } { @@ -106,9 +115,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 7); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7); - EXPECT_EQ(db, std::numeric_limits<double>::max()); + EXPECT_EQ(db, std::numeric_limits<double>::infinity()); } { @@ -116,7 +125,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, 7); } @@ -126,7 +135,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_FALSE(q.getAsIntegerTerm(ia, ib)); // This is dubious and perhaps a regression. EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7.1); EXPECT_EQ(db, 7.1); } @@ -136,7 +145,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_FALSE(q.getAsIntegerTerm(ia, ib)); // This is dubious and perhaps a regression. EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 500.0); EXPECT_EQ(db, std::numeric_limits<double>::max()); } @@ -147,8 +156,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, std::nextafterf(minusSeven, seven)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, std::nextafter(minusSeven, seven)); EXPECT_EQ(db, seven); } @@ -157,9 +166,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, std::nextafterf(minusSeven, seven)); - EXPECT_EQ(db, std::nextafterf(seven, minusSeven)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, std::nextafter(minusSeven, seven)); + EXPECT_EQ(db, std::nextafter(seven, minusSeven)); } { @@ -174,9 +183,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, minusSeven); - EXPECT_EQ(db, std::nextafterf(seven, minusSeven)); + EXPECT_EQ(db, std::nextafter(seven, minusSeven)); } { @@ -184,8 +193,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, -8); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits<double>::max()); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, -std::numeric_limits<double>::infinity()); EXPECT_LT(db, -7); EXPECT_GT(db, -7.01); } @@ -195,8 +204,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits<double>::max()); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, -std::numeric_limits<double>::infinity()); EXPECT_EQ(db, -7); } @@ -205,8 +214,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits<int64_t>::min()); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits<double>::max()); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, -std::numeric_limits<double>::infinity()); EXPECT_EQ(db, -7); } @@ -215,10 +224,10 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, -7); EXPECT_LT(da, -6.99); - EXPECT_EQ(db, std::numeric_limits<double>::max()); + EXPECT_EQ(db, std::numeric_limits<double>::infinity()); } { @@ -226,9 +235,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); - EXPECT_EQ(db, std::numeric_limits<double>::max()); + EXPECT_EQ(db, std::numeric_limits<double>::infinity()); } { @@ -236,15 +245,15 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, std::numeric_limits<int64_t>::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); - EXPECT_EQ(db, std::numeric_limits<double>::max()); + EXPECT_EQ(db, std::numeric_limits<double>::infinity()); } { QueryTerm q(factory.create(), "a", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(!q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(!q.getAsFloatTerm(da, db)); } { @@ -287,7 +296,10 @@ TEST(StreamingQueryTest, test_query_language) class AllowRewrite : public QueryNodeResultFactory { public: - virtual bool getRewriteFloatTerms() const override { return true; } + explicit AllowRewrite(vespalib::stringref index) noexcept : _allowedIndex(index) {} + bool getRewriteFloatTerms(vespalib::stringref index) const noexcept override { return index == _allowedIndex; } +private: + vespalib::string _allowedIndex; }; const char TERM_UNIQ = static_cast<char>(ParseItem::ITEM_TERM) | static_cast<char>(ParseItem::IF_UNIQUEID); @@ -297,12 +309,12 @@ TEST(StreamingQueryTest, e_is_not_rewritten_even_if_allowed) const char term[6] = {TERM_UNIQ, 3, 1, 'c', 1, 'e'}; vespalib::stringref stackDump(term, sizeof(term)); EXPECT_EQ(6u, stackDump.size()); - AllowRewrite allowRewrite; + AllowRewrite allowRewrite("c"); const Query q(allowRewrite, stackDump); EXPECT_TRUE(q.valid()); const QueryNode & root = q.getRoot(); EXPECT_TRUE(dynamic_cast<const QueryTerm *>(&root) != nullptr); - const QueryTerm & qt = static_cast<const QueryTerm &>(root); + const auto & qt = static_cast<const QueryTerm &>(root); EXPECT_EQ("c", qt.index()); EXPECT_EQ(vespalib::stringref("e"), qt.getTerm()); EXPECT_EQ(3u, qt.uniqueId()); @@ -313,12 +325,12 @@ TEST(StreamingQueryTest, onedot0e_is_not_rewritten_by_default) const char term[9] = {TERM_UNIQ, 3, 1, 'c', 4, '1', '.', '0', 'e'}; vespalib::stringref stackDump(term, sizeof(term)); EXPECT_EQ(9u, stackDump.size()); - QueryNodeResultFactory empty; + AllowRewrite empty("nix"); const Query q(empty, stackDump); EXPECT_TRUE(q.valid()); const QueryNode & root = q.getRoot(); EXPECT_TRUE(dynamic_cast<const QueryTerm *>(&root) != nullptr); - const QueryTerm & qt = static_cast<const QueryTerm &>(root); + const auto & qt = static_cast<const QueryTerm &>(root); EXPECT_EQ("c", qt.index()); EXPECT_EQ(vespalib::stringref("1.0e"), qt.getTerm()); EXPECT_EQ(3u, qt.uniqueId()); @@ -329,34 +341,34 @@ TEST(StreamingQueryTest, onedot0e_is_rewritten_if_allowed_too) const char term[9] = {TERM_UNIQ, 3, 1, 'c', 4, '1', '.', '0', 'e'}; vespalib::stringref stackDump(term, sizeof(term)); EXPECT_EQ(9u, stackDump.size()); - AllowRewrite empty; + AllowRewrite empty("c"); const Query q(empty, stackDump); EXPECT_TRUE(q.valid()); const QueryNode & root = q.getRoot(); EXPECT_TRUE(dynamic_cast<const EquivQueryNode *>(&root) != nullptr); - const EquivQueryNode & equiv = static_cast<const EquivQueryNode &>(root); + const auto & equiv = static_cast<const EquivQueryNode &>(root); EXPECT_EQ(2u, equiv.size()); EXPECT_TRUE(dynamic_cast<const QueryTerm *>(equiv[0].get()) != nullptr); { - const QueryTerm & qt = static_cast<const QueryTerm &>(*equiv[0]); + const auto & qt = static_cast<const QueryTerm &>(*equiv[0]); EXPECT_EQ("c", qt.index()); EXPECT_EQ(vespalib::stringref("1.0e"), qt.getTerm()); EXPECT_EQ(3u, qt.uniqueId()); } EXPECT_TRUE(dynamic_cast<const PhraseQueryNode *>(equiv[1].get()) != nullptr); { - const PhraseQueryNode & phrase = static_cast<const PhraseQueryNode &>(*equiv[1]); + const auto & phrase = static_cast<const PhraseQueryNode &>(*equiv[1]); EXPECT_EQ(2u, phrase.size()); EXPECT_TRUE(dynamic_cast<const QueryTerm *>(phrase[0].get()) != nullptr); { - const QueryTerm & qt = static_cast<const QueryTerm &>(*phrase[0]); + const auto & qt = static_cast<const QueryTerm &>(*phrase[0]); EXPECT_EQ("c", qt.index()); EXPECT_EQ(vespalib::stringref("1"), qt.getTerm()); EXPECT_EQ(0u, qt.uniqueId()); } EXPECT_TRUE(dynamic_cast<const QueryTerm *>(phrase[1].get()) != nullptr); { - const QueryTerm & qt = static_cast<const QueryTerm &>(*phrase[1]); + const auto & qt = static_cast<const QueryTerm &>(*phrase[1]); EXPECT_EQ("c", qt.index()); EXPECT_EQ(vespalib::stringref("0e"), qt.getTerm()); EXPECT_EQ(0u, qt.uniqueId()); @@ -460,7 +472,7 @@ TEST(StreamingQueryTest, test_phrase_evaluate) terms[1]->add(1, 5, 0, 1); terms[2]->add(0, 5, 0, 1); HitList hits; - PhraseQueryNode * p = static_cast<PhraseQueryNode *>(phrases[0]); + auto * p = static_cast<PhraseQueryNode *>(phrases[0]); p->evaluateHits(hits); ASSERT_EQ(3u, hits.size()); EXPECT_EQ(hits[0].wordpos(), 2u); @@ -642,11 +654,11 @@ TEST(StreamingQueryTest, require_that_ascending_range_can_be_specified_with_limi QueryTerm ascending_query(eqnr.create(), "[;;500]", "index", TermType::WORD); EXPECT_TRUE(ascending_query.getAsIntegerTerm(low_integer, high_integer)); - EXPECT_TRUE(ascending_query.getAsDoubleTerm(low_double, high_double)); + EXPECT_TRUE(ascending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits<int64_t>::min(), low_integer); EXPECT_EQ(std::numeric_limits<int64_t>::max(), high_integer); - EXPECT_EQ(-std::numeric_limits<double>::max(), low_double); - EXPECT_EQ(std::numeric_limits<double>::max(), high_double); + EXPECT_EQ(-std::numeric_limits<double>::infinity(), low_double); + EXPECT_EQ(std::numeric_limits<double>::infinity(), high_double); EXPECT_EQ(500, ascending_query.getRangeLimit()); } @@ -661,11 +673,11 @@ TEST(StreamingQueryTest, require_that_descending_range_can_be_specified_with_lim QueryTerm descending_query(eqnr.create(), "[;;-500]", "index", TermType::WORD); EXPECT_TRUE(descending_query.getAsIntegerTerm(low_integer, high_integer)); - EXPECT_TRUE(descending_query.getAsDoubleTerm(low_double, high_double)); + EXPECT_TRUE(descending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits<int64_t>::min(), low_integer); EXPECT_EQ(std::numeric_limits<int64_t>::max(), high_integer); - EXPECT_EQ(-std::numeric_limits<double>::max(), low_double); - EXPECT_EQ(std::numeric_limits<double>::max(), high_double); + EXPECT_EQ(-std::numeric_limits<double>::infinity(), low_double); + EXPECT_EQ(std::numeric_limits<double>::infinity(), high_double); EXPECT_EQ(-500, descending_query.getRangeLimit()); } @@ -750,7 +762,7 @@ TEST(StreamingQueryTest, require_that_incorrectly_specified_diversity_can_be_par TEST(StreamingQueryTest, require_that_we_do_not_break_the_stack_on_bad_query) { - QueryTermSimple term("<form><iframe+	 +src=\\\"javascript:alert(1)\\\" 	;>", TermType::WORD); + QueryTermSimple term(R"(<form><iframe+	 +src=\"javascript:alert(1)\" 	;>)", TermType::WORD); EXPECT_FALSE(term.isValid()); } @@ -759,7 +771,7 @@ TEST(StreamingQueryTest, 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_EQ(85u, stackDump.size()); - AllowRewrite empty; + AllowRewrite empty(""); const Query q(empty, stackDump); EXPECT_TRUE(q.valid()); const QueryNode & root = q.getRoot(); @@ -793,7 +805,7 @@ TEST(StreamingQueryTest, test_same_element_evaluate) vespalib::string stackDump = StackDumpCreator::create(*node); QueryNodeResultFactory empty; Query q(empty, stackDump); - SameElementQueryNode * sameElem = dynamic_cast<SameElementQueryNode *>(&q.getRoot()); + auto * sameElem = dynamic_cast<SameElementQueryNode *>(&q.getRoot()); EXPECT_TRUE(sameElem != nullptr); EXPECT_EQ("field", sameElem->getIndex()); EXPECT_EQ(3u, sameElem->size()); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index fb2be58c536..e6cea9c752b 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -4,7 +4,6 @@ #include "base.h" #include <vespa/vespalib/objects/visit.h> #include <vespa/vespalib/util/classname.h> -#include <vespa/vespalib/locale/c.h> #include <cmath> #include <limits> #include <charconv> @@ -12,11 +11,59 @@ namespace { template <typename N> -bool isValidInteger(int64_t value) +constexpr bool isValidInteger(int64_t value) noexcept { - return value >= std::numeric_limits<N>::min() && value <= std::numeric_limits<N>::max(); + return (value >= std::numeric_limits<N>::min()) && + (value <= std::numeric_limits<N>::max()); } +constexpr bool isRepresentableByInt64(double d) noexcept { + return (d > double(std::numeric_limits<int64_t>::min())) && + (d < double(std::numeric_limits<int64_t>::max())); +} + +bool isFullRange(vespalib::stringref s) noexcept { + const size_t sz(s.size()); + return (sz >= 3u) && + (s[0] == '<' || s[0] == '[') && + (s[sz-1] == '>' || s[sz-1] == ']'); +} + +struct IntDecoder { + static int64_t fromstr(const char * q, const char * qend, const char ** end) noexcept { + int64_t v(0); + for (;q < qend && (isspace(*q) || (*q == '+')); q++); + std::from_chars_result err = std::from_chars(q, qend, v, 10); + if (err.ec == std::errc::result_out_of_range) { + v = (*q == '-') ? std::numeric_limits<int64_t>::min() : std::numeric_limits<int64_t>::max(); + } + *end = err.ptr; + return v; + } + static int64_t nearestDownwd(int64_t n, int64_t min) noexcept { return (n > min ? n - 1 : n); } + static int64_t nearestUpward(int64_t n, int64_t max) noexcept { return (n < max ? n + 1 : n); } +}; + +template <typename T> +struct FloatDecoder { + static T fromstr(const char * q, const char * qend, const char ** end) noexcept { + T v(0); + for (;q < qend && (isspace(*q) || (*q == '+')); q++); + std::from_chars_result err = std::from_chars(q, qend, v); + if (err.ec == std::errc::result_out_of_range) { + v = (*q == '-') ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity(); + } + *end = err.ptr; + return v; + } + static T nearestDownwd(T n, T min) noexcept { + return std::nextafter(n, min); + } + static T nearestUpward(T n, T max) noexcept { + return std::nextafter(n, max); + } +}; + } namespace search { @@ -30,15 +77,15 @@ QueryTermSimple::visitMembers(vespalib::ObjectVisitor & visitor) const template <typename N> QueryTermSimple::RangeResult<N> -QueryTermSimple::getFloatRange() const +QueryTermSimple::getFloatRange() const noexcept { - double lowRaw, highRaw; - bool valid = getAsDoubleTerm(lowRaw, highRaw); + N lowRaw, highRaw; + bool valid = getAsFloatTerm(lowRaw, highRaw); RangeResult<N> res; res.valid = valid; if (!valid) { - res.low = std::numeric_limits<N>::max(); - res.high = - std::numeric_limits<N>::max(); + res.low = std::numeric_limits<N>::infinity(); + res.high = -std::numeric_limits<N>::infinity(); res.adjusted = true; } else { res.low = lowRaw; @@ -47,25 +94,16 @@ QueryTermSimple::getFloatRange() const return res; } -namespace { - -bool isRepresentableByInt64(double d) { - return (d > double(std::numeric_limits<int64_t>::min())) - && (d < double(std::numeric_limits<int64_t>::max())); -} - -} - bool -QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const +QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const noexcept { bool valid = getAsIntegerTerm(low, high); if ( ! valid ) { double l(0), h(0); - valid = getAsDoubleTerm(l, h); + valid = getAsFloatTerm(l, h); if (valid) { if ((l == h) && isRepresentableByInt64(l)) { - low = high = std::round(l); + low = high = static_cast<int64_t>(std::round(l)); } else { if (l > double(std::numeric_limits<int64_t>::min())) { if (l < double(std::numeric_limits<int64_t>::max())) { @@ -89,7 +127,7 @@ QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const template <typename N> QueryTermSimple::RangeResult<N> -QueryTermSimple::getIntegerRange() const +QueryTermSimple::getIntegerRange() const noexcept { int64_t lowRaw, highRaw; bool valid = getRangeInternal(lowRaw, highRaw); @@ -122,94 +160,72 @@ QueryTermSimple::getIntegerRange() const template <> QueryTermSimple::RangeResult<float> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getFloatRange<float>(); } template <> QueryTermSimple::RangeResult<double> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getFloatRange<double>(); } template <> QueryTermSimple::RangeResult<int8_t> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange<int8_t>(); } template <> QueryTermSimple::RangeResult<int16_t> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange<int16_t>(); } template <> QueryTermSimple::RangeResult<int32_t> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange<int32_t>(); } template <> QueryTermSimple::RangeResult<int64_t> -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange<int64_t>(); } -struct IntDecoder { - static int64_t fromstr(const char * q, const char * qend, char ** end) noexcept { - int64_t v(0); - for (;q < qend && isspace(*q); q++); - std::from_chars_result err = std::from_chars(q, qend, v, 10); - if (err.ec == std::errc::result_out_of_range) { - v = (*q == '-') ? std::numeric_limits<int64_t>::min() : std::numeric_limits<int64_t>::max(); - } - *end = const_cast<char *>(err.ptr); - return v; - } - static int64_t nearestDownwd(int64_t n, int64_t min) noexcept { return (n > min ? n - 1 : n); } - static int64_t nearestUpward(int64_t n, int64_t max) noexcept { return (n < max ? n + 1 : n); } -}; - -struct DoubleDecoder { - static double fromstr(const char * q, const char * qend, char ** end) { - (void) qend; - return vespalib::locale::c::strtod(q, end); - } - static double nearestDownwd(double n, double min) noexcept { return std::nextafterf(n, min); } - static double nearestUpward(double n, double max) noexcept { return std::nextafterf(n, max); } -}; - -bool QueryTermSimple::getAsIntegerTerm(int64_t & lower, int64_t & upper) const +bool QueryTermSimple::getAsIntegerTerm(int64_t & lower, int64_t & upper) const noexcept { lower = std::numeric_limits<int64_t>::min(); upper = std::numeric_limits<int64_t>::max(); return getAsNumericTerm(lower, upper, IntDecoder()); } -bool QueryTermSimple::getAsDoubleTerm(double & lower, double & upper) const +bool QueryTermSimple::getAsFloatTerm(double & lower, double & upper) const noexcept +{ + lower = -std::numeric_limits<double>::infinity(); + upper = std::numeric_limits<double>::infinity(); + return getAsNumericTerm(lower, upper, FloatDecoder<double>()); +} + +bool QueryTermSimple::getAsFloatTerm(float & lower, float & upper) const noexcept { - lower = - std::numeric_limits<double>::max(); - upper = std::numeric_limits<double>::max(); - return getAsNumericTerm(lower, upper, DoubleDecoder()); + lower = -std::numeric_limits<float>::infinity(); + upper = std::numeric_limits<float>::infinity(); + return getAsNumericTerm(lower, upper, FloatDecoder<float>()); } QueryTermSimple::~QueryTermSimple() = default; namespace { -bool isFullRange(vespalib::stringref s) { - const size_t sz(s.size()); - return (sz >= 3u) && - (s[0] == '<' || s[0] == '[') && - (s[sz-1] == '>' || s[sz-1] == ']'); -} + } @@ -244,7 +260,7 @@ QueryTermSimple::QueryTermSimple(const string & term_, Type type) } _valid = (numParts >= 2) && (numParts < NELEMS(parts)); if (_valid && numParts > 2) { - _rangeLimit = strtol(parts[2].data(), nullptr, 0); + _rangeLimit = static_cast<int32_t>(strtol(parts[2].data(), nullptr, 0)); if (numParts > 3) { _valid = (numParts >= 5); if (_valid) { @@ -269,12 +285,12 @@ QueryTermSimple::QueryTermSimple(const string & term_, Type type) template <typename T, typename D> bool -QueryTermSimple::getAsNumericTerm(T & lower, T & upper, D d) const +QueryTermSimple::getAsNumericTerm(T & lower, T & upper, D d) const noexcept { if (empty()) return false; size_t sz(_term.size()); - char *err(nullptr); + const char *err(nullptr); T low(lower); T high(upper); const char * q = _term.c_str(); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.h b/searchlib/src/vespa/searchlib/query/query_term_simple.h index 2b64e3812ab..87bf7c26b80 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.h +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.h @@ -33,8 +33,8 @@ public: N high; bool valid; // Whether parsing of the range was successful bool adjusted; // Whether the low and high was adjusted according to min and max limits of the given type. - RangeResult() : low(), high(), valid(true), adjusted(false) {} - bool isEqual() const { return low == high; } + RangeResult() noexcept : low(), high(), valid(true), adjusted(false) {} + bool isEqual() const noexcept { return low == high; } }; QueryTermSimple(const QueryTermSimple &) = delete; @@ -47,39 +47,40 @@ public: * Extracts the content of this query term as a range with low and high values. */ template <typename N> - RangeResult<N> getRange() const; - int getRangeLimit() const { return _rangeLimit; } - size_t getMaxPerGroup() const { return _maxPerGroup; } - size_t getDiversityCutoffGroups() const { return _diversityCutoffGroups; } - bool getDiversityCutoffStrict() const { return _diversityCutoffStrict; } - vespalib::stringref getDiversityAttribute() const { return _diversityAttribute; } - size_t getFuzzyMaxEditDistance() const { return _fuzzyMaxEditDistance; } - size_t getFuzzyPrefixLength() const { return _fuzzyPrefixLength; } - bool getAsIntegerTerm(int64_t & lower, int64_t & upper) const; - bool getAsDoubleTerm(double & lower, double & upper) const; - const char * getTerm() const { return _term.c_str(); } - bool isPrefix() const { return (_type == Type::PREFIXTERM); } - bool isSubstring() const { return (_type == Type::SUBSTRINGTERM); } - bool isExactstring() const { return (_type == Type::EXACTSTRINGTERM); } - bool isSuffix() const { return (_type == Type::SUFFIXTERM); } - bool isWord() const { return (_type == Type::WORD); } - bool isRegex() const { return (_type == Type::REGEXP); } - bool isGeoLoc() const { return (_type == Type::GEO_LOCATION); } - bool isFuzzy() const { return (_type == Type::FUZZYTERM); } + RangeResult<N> getRange() const noexcept; + int getRangeLimit() const noexcept { return _rangeLimit; } + size_t getMaxPerGroup() const noexcept { return _maxPerGroup; } + size_t getDiversityCutoffGroups() const noexcept { return _diversityCutoffGroups; } + bool getDiversityCutoffStrict() const noexcept { return _diversityCutoffStrict; } + vespalib::stringref getDiversityAttribute() const noexcept { return _diversityAttribute; } + size_t getFuzzyMaxEditDistance() const noexcept { return _fuzzyMaxEditDistance; } + size_t getFuzzyPrefixLength() const noexcept { return _fuzzyPrefixLength; } + bool getAsIntegerTerm(int64_t & lower, int64_t & upper) const noexcept; + bool getAsFloatTerm(double & lower, double & upper) const noexcept; + bool getAsFloatTerm(float & lower, float & upper) const noexcept; + const char * getTerm() const noexcept { return _term.c_str(); } + bool isPrefix() const noexcept { return (_type == Type::PREFIXTERM); } + bool isSubstring() const noexcept { return (_type == Type::SUBSTRINGTERM); } + bool isExactstring() const noexcept { return (_type == Type::EXACTSTRINGTERM); } + bool isSuffix() const noexcept { return (_type == Type::SUFFIXTERM); } + bool isWord() const noexcept { return (_type == Type::WORD); } + bool isRegex() const noexcept { return (_type == Type::REGEXP); } + bool isGeoLoc() const noexcept { return (_type == Type::GEO_LOCATION); } + bool isFuzzy() const noexcept { return (_type == Type::FUZZYTERM); } bool is_nearest_neighbor() const noexcept { return (_type == Type::NEAREST_NEIGHBOR); } - bool empty() const { return _term.empty(); } + bool empty() const noexcept { return _term.empty(); } virtual void visitMembers(vespalib::ObjectVisitor &visitor) const; vespalib::string getClassName() const; - bool isValid() const { return _valid; } - const string & getTermString() const { return _term; } + bool isValid() const noexcept { return _valid; } + const string & getTermString() const noexcept { return _term; } private: - bool getRangeInternal(int64_t & low, int64_t & high) const; + bool getRangeInternal(int64_t & low, int64_t & high) const noexcept; template <typename N> - RangeResult<N> getIntegerRange() const; + RangeResult<N> getIntegerRange() const noexcept; template <typename N> - RangeResult<N> getFloatRange() const; - int _rangeLimit; + RangeResult<N> getFloatRange() const noexcept; + int32_t _rangeLimit; uint32_t _maxPerGroup; uint32_t _diversityCutoffGroups; Type _type; @@ -88,7 +89,7 @@ private: string _term; stringref _diversityAttribute; template <typename T, typename D> - bool getAsNumericTerm(T & lower, T & upper, D d) const; + bool getAsNumericTerm(T & lower, T & upper, D d) const noexcept; protected: uint32_t _fuzzyMaxEditDistance; // set in QueryTerm diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index 6b3aa7a2fd0..9484999f45a 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -156,7 +156,7 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor qt->setFuzzyMaxEditDistance(queryRep.getFuzzyMaxEditDistance()); qt->setFuzzyPrefixLength(queryRep.getFuzzyPrefixLength()); } - if (possibleFloat(*qt, ssTerm) && factory.getRewriteFloatTerms() && allowRewrite) { + if (allowRewrite && possibleFloat(*qt, ssTerm) && factory.getRewriteFloatTerms(ssIndex)) { auto phrase = std::make_unique<PhraseQueryNode>(); auto dotPos = ssTerm.find('.'); phrase->addChild(std::make_unique<QueryTerm>(factory.create(), ssTerm.substr(0, dotPos), ssIndex, TermType::WORD)); diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynoderesultbase.h b/searchlib/src/vespa/searchlib/query/streaming/querynoderesultbase.h index 10f3b7cbf21..d7704fb60e1 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynoderesultbase.h +++ b/searchlib/src/vespa/searchlib/query/streaming/querynoderesultbase.h @@ -1,6 +1,7 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once +#include <vespa/vespalib/stllike/string.h> #include <memory> namespace search::streaming { @@ -20,7 +21,7 @@ public: class QueryNodeResultFactory { public: virtual ~QueryNodeResultFactory() = default; - virtual bool getRewriteFloatTerms() const { return false; } + virtual bool getRewriteFloatTerms(vespalib::stringref index) const noexcept { (void) index; return false; } virtual std::unique_ptr<QueryNodeResultBase> create() const { return {}; } }; } diff --git a/streamingvisitors/src/tests/rank_processor/rank_processor_test.cpp b/streamingvisitors/src/tests/rank_processor/rank_processor_test.cpp index 2d138d1d336..93e35e4c6d2 100644 --- a/streamingvisitors/src/tests/rank_processor/rank_processor_test.cpp +++ b/streamingvisitors/src/tests/rank_processor/rank_processor_test.cpp @@ -40,7 +40,7 @@ protected: RankProcessorTest::RankProcessorTest() : testing::Test(), - _factory(), + _factory(nullptr), _query(), _query_wrapper() { diff --git a/streamingvisitors/src/vespa/searchvisitor/querytermdata.h b/streamingvisitors/src/vespa/searchvisitor/querytermdata.h index 8c1c3771917..36176f70d1d 100644 --- a/streamingvisitors/src/vespa/searchvisitor/querytermdata.h +++ b/streamingvisitors/src/vespa/searchvisitor/querytermdata.h @@ -17,15 +17,26 @@ private: search::fef::SimpleTermData _termData; public: QueryTermData * clone() const override { return new QueryTermData(); } - search::fef::SimpleTermData &getTermData() { return _termData; } + search::fef::SimpleTermData &getTermData() noexcept { return _termData; } +}; + +class SearchMethodInfo { +public: + virtual ~SearchMethodInfo() = default; + virtual bool is_text_matching(vespalib::stringref index) const noexcept = 0; }; class QueryTermDataFactory final : public search::streaming::QueryNodeResultFactory { public: + QueryTermDataFactory(const SearchMethodInfo * searchMethodInfo) noexcept : _searchMethodInfo(searchMethodInfo) {} std::unique_ptr<search::streaming::QueryNodeResultBase> create() const override { return std::make_unique<QueryTermData>(); } - bool getRewriteFloatTerms() const override { return true; } + bool getRewriteFloatTerms(vespalib::stringref index ) const noexcept override { + return _searchMethodInfo && _searchMethodInfo->is_text_matching(index); + } +private: + const SearchMethodInfo * _searchMethodInfo; }; diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp index 4d31c71c0a0..49604135afc 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp @@ -91,7 +91,7 @@ ForceWordfolderInit::ForceWordfolderInit() Fast_NormalizeWordFolder::DO_MULTICHAR_EXPANSION); } -static ForceWordfolderInit _G_forceNormWordFolderInit; +static ForceWordfolderInit G_forceNormWordFolderInit; // Leftovers from FS4 protocol with limited use here. enum queryflags { @@ -238,14 +238,16 @@ SearchVisitor::SummaryGenerator::fillSummary(AttributeVector::DocId lid, const H return {}; } -void SearchVisitor::HitsResultPreparator::execute(vespalib::Identifiable & obj) +void +SearchVisitor::HitsResultPreparator::execute(vespalib::Identifiable & obj) { auto & hitsAggr(static_cast<HitsAggregationResult &>(obj)); hitsAggr.setSummaryGenerator(_summaryGenerator); _numHitsAggregators++; } -bool SearchVisitor::HitsResultPreparator::check(const vespalib::Identifiable & obj) const +bool +SearchVisitor::HitsResultPreparator::check(const vespalib::Identifiable & obj) const { return obj.getClass().inherits(HitsAggregationResult::classId); } @@ -259,7 +261,8 @@ SearchVisitor::GroupingEntry::GroupingEntry(Grouping * grouping) : SearchVisitor::GroupingEntry::~GroupingEntry() = default; -void SearchVisitor::GroupingEntry::aggregate(const document::Document & doc, search::HitRank rank) +void +SearchVisitor::GroupingEntry::aggregate(const document::Document & doc, search::HitRank rank) { if (_count < _limit) { _grouping->aggregate(doc, rank); @@ -310,7 +313,21 @@ SearchVisitor::SearchVisitor(StorageComponent& component, LOG(debug, "Created SearchVisitor"); } -void SearchVisitor::init(const Parameters & params) +bool +SearchVisitor::is_text_matching(vespalib::stringref index) const noexcept { + StringFieldIdTMap fieldIdMap; + _fieldSearchSpecMap.addFieldsFromIndex(index, fieldIdMap); + for (const auto & fieldId : fieldIdMap.map()) { + auto found = _fieldSearchSpecMap.specMap().find(fieldId.second); + if ((found != _fieldSearchSpecMap.specMap().end()) && found->second.uses_string_search_method()) { + return true; + } + } + return false; +} + +void +SearchVisitor::init(const Parameters & params) { VISITOR_TRACE(6, "About to lazily init VSM adapter"); _attrMan.add(_documentIdAttributeBacking); @@ -397,7 +414,14 @@ void SearchVisitor::init(const Parameters & params) if ( params.lookup("query", queryBlob) ) { LOG(spam, "Received query blob of %zu bytes", queryBlob.size()); VISITOR_TRACE(9, vespalib::make_string("Setting up for query blob of %zu bytes", queryBlob.size())); - QueryTermDataFactory addOnFactory; + // Create mapping from field name to field id, from field id to search spec, + // and from index name to list of field ids + _fieldSearchSpecMap.buildFromConfig(_env->get_vsm_fields_config()); + auto additionalFields = registerAdditionalFields(_env->get_docsum_tools()->getFieldSpecs()); + // Add extra elements to mapping from field name to field id + _fieldSearchSpecMap.buildFromConfig(additionalFields); + + QueryTermDataFactory addOnFactory(this); _query = Query(addOnFactory, vespalib::stringref(queryBlob.data(), queryBlob.size())); _searchBuffer->reserve(0x10000); @@ -408,19 +432,11 @@ void SearchVisitor::init(const Parameters & params) LOG(warning, "Request without query stack count"); } - std::vector<vespalib::string> additionalFields; - registerAdditionalFields(_env->get_docsum_tools()->getFieldSpecs(), additionalFields); - - StringFieldIdTMap fieldsInQuery; - setupFieldSearchers(additionalFields, fieldsInQuery); - - + StringFieldIdTMap fieldsInQuery = setupFieldSearchers(); setupScratchDocument(fieldsInQuery); - _syntheticFieldsController.setup(_fieldSearchSpecMap.nameIdMap(), fieldsInQuery); setupAttributeVectors(); - setupAttributeVectorsForSorting(_sortSpec); _rankController.setRankManagerSnapshot(_env->get_rank_manager_snapshot()); @@ -436,7 +452,6 @@ void SearchVisitor::init(const Parameters & params) // This depends on _fieldPathMap (from setupScratchDocument), // and IQueryEnvironment (from setupRankProcessors). prepare_field_searchers(); - } else { LOG(warning, "No query received"); } @@ -529,10 +544,7 @@ SearchVisitor::PositionInserter::PositionInserter(AttributeVector & attribute, A SearchVisitor::PositionInserter::~PositionInserter() = default; void -SearchVisitor::PositionInserter::onPrimitive(uint32_t, const Content & c) -{ - (void) c; -} +SearchVisitor::PositionInserter::onPrimitive(uint32_t, const Content &) { } void SearchVisitor::PositionInserter::onStructStart(const Content & c) @@ -605,7 +617,6 @@ SearchVisitor::RankController::setupRankProcessors(Query & query, { _rankSetup = &_rankManagerSnapshot->getRankSetup(_rankProfile); _rankProcessor = std::make_unique<RankProcessor>(_rankManagerSnapshot, _rankProfile, query, location, _queryProperties, &attrMan); - LOG(debug, "Initialize rank processor"); _rankProcessor->initForRanking(wantedHitCount); // register attribute vectors needed for ranking processAccessedAttributes(_rankProcessor->get_real_query_env(), true, attrMan, attributeFields); @@ -637,8 +648,7 @@ SearchVisitor::RankController::rankMatchedDocument(uint32_t docId) { _rankProcessor->runRankProgram(docId); LOG(debug, "Rank score for matched document %u: %f", - docId, - _rankProcessor->getRankScore()); + docId, _rankProcessor->getRankScore()); if (_dumpFeatures) { _dumpProcessor->runRankProgram(docId); // we must transfer the score to this match data to make sure that the same hits @@ -718,9 +728,8 @@ SearchVisitor::SyntheticFieldsController::setup(const StringFieldIdTMap & fieldR } void -SearchVisitor::SyntheticFieldsController::onDocument(StorageDocument & document) +SearchVisitor::SyntheticFieldsController::onDocument(StorageDocument &) { - (void) document; } void @@ -730,10 +739,10 @@ SearchVisitor::SyntheticFieldsController::onDocumentMatch(StorageDocument & docu document.setField(_documentIdFId, std::make_unique<document::StringFieldValue>(documentId)); } -void -SearchVisitor::registerAdditionalFields(const std::vector<vsm::DocsumTools::FieldSpec> & docsumSpec, - std::vector<vespalib::string> & fieldList) +std::vector<vespalib::string> +SearchVisitor::registerAdditionalFields(const std::vector<vsm::DocsumTools::FieldSpec> & docsumSpec) { + std::vector<vespalib::string> fieldList; for (const vsm::DocsumTools::FieldSpec & spec : docsumSpec) { fieldList.push_back(spec.getOutputName()); const std::vector<vespalib::string> & inputNames = spec.getInputNames(); @@ -748,25 +757,20 @@ SearchVisitor::registerAdditionalFields(const std::vector<vsm::DocsumTools::Fiel fieldList.emplace_back("[docid]"); fieldList.emplace_back("[rank]"); fieldList.emplace_back("documentid"); + return fieldList; } -void -SearchVisitor::setupFieldSearchers(const std::vector<vespalib::string> & additionalFields, - StringFieldIdTMap & fieldsInQuery) +StringFieldIdTMap +SearchVisitor::setupFieldSearchers() { - // Create mapping from field name to field id, from field id to search spec, - // and from index name to list of field ids - _fieldSearchSpecMap.buildFromConfig(_env->get_vsm_fields_config()); - // Add extra elements to mapping from field name to field id - _fieldSearchSpecMap.buildFromConfig(additionalFields); - // Reconfig field searchers based on the query _fieldSearchSpecMap.reconfigFromQuery(_query); // Map field name to field id for all fields in the query - _fieldSearchSpecMap.buildFieldsInQuery(_query, fieldsInQuery); + StringFieldIdTMap fieldsInQuery = _fieldSearchSpecMap.buildFieldsInQuery(_query); // Connect field names in the query to field searchers _fieldSearchSpecMap.buildSearcherMap(fieldsInQuery.map(), _fieldSearcherMap); + return fieldsInQuery; } void @@ -947,8 +951,7 @@ class SingleDocumentStore : public vsm::IDocSumCache { public: explicit SingleDocumentStore(const StorageDocument & doc) : _doc(doc) { } - const vsm::Document & getDocSum(const search::DocumentIdT & docId) const override { - (void) docId; + const vsm::Document & getDocSum(const search::DocumentIdT &) const override { return _doc; } private: @@ -959,19 +962,12 @@ bool SearchVisitor::compatibleDocumentTypes(const document::DocumentType& typeA, const document::DocumentType& typeB) { - if (&typeA == &typeB) { - return true; - } else { - return (typeA.getName() == typeB.getName()); - } + return (&typeA == &typeB) || (typeA.getName() == typeB.getName()); } void -SearchVisitor::handleDocuments(const document::BucketId&, - DocEntryList & entries, - HitCounter& hitCounter) +SearchVisitor::handleDocuments(const document::BucketId&, DocEntryList & entries, HitCounter& ) { - (void) hitCounter; if (!_init_called) { init(_params); } @@ -1016,37 +1012,25 @@ SearchVisitor::handleDocument(StorageDocument & document) RankProcessor & rp = *_rankController.getRankProcessor(); vespalib::string documentId(document.docDoc().getId().getScheme().toString()); LOG(debug, "Matched document with id '%s'", documentId.c_str()); - document.setDocId(rp.getDocId()); - fillAttributeVectors(documentId, document); - _rankController.rankMatchedDocument(rp.getDocId()); - if (_shouldFillRankAttribute) { _rankAttribute.add(rp.getRankScore()); } - if (_rankController.keepMatchedDocument()) { - bool amongTheBest = _rankController.collectMatchedDocument(!_sortList.empty(), *this, _tmpSortBuffer, &document); - _syntheticFieldsController.onDocumentMatch(document, documentId); - SingleDocumentStore single(document); _summaryGenerator.setDocsumCache(single); group(document.docDoc(), rp.getRankScore(), false); - if (amongTheBest) { needToKeepDocument = true; } - } else { _hitsRejectedCount++; LOG(debug, "Do not keep document with id '%s' because rank score (%f) <= rank score drop limit (%f)", - documentId.c_str(), - rp.getRankScore(), - _rankController.getRankSetup()->getRankScoreDropLimit()); + documentId.c_str(), rp.getRankScore(), _rankController.getRankSetup()->getRankScoreDropLimit()); } } else { LOG(debug, "Did not match document with id '%s'", document.docDoc().getId().getScheme().toString().c_str()); @@ -1145,7 +1129,8 @@ SearchVisitor::fillSortBuffer() return pos; } -void SearchVisitor::completedBucket(const document::BucketId&, HitCounter&) +void +SearchVisitor::completedBucket(const document::BucketId&, HitCounter&) { LOG(debug, "Completed bucket"); } @@ -1157,7 +1142,8 @@ SearchVisitor::generate_query_result(HitCounter& counter) return std::move(_queryResult); } -void SearchVisitor::completedVisitingInternal(HitCounter& hitCounter) +void +SearchVisitor::completedVisitingInternal(HitCounter& hitCounter) { if (!_init_called) { init(_params); diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h index ef7a41f23a5..709564bcf02 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h @@ -8,6 +8,7 @@ #include "rankmanager.h" #include "rankprocessor.h" #include "searchenvironment.h" +#include "querytermdata.h" #include <vespa/vsm/common/docsum.h> #include <vespa/vsm/common/documenttypemapping.h> #include <vespa/vsm/common/storagedocument.h> @@ -42,7 +43,8 @@ class SearchEnvironmentSnapshot; * @brief Visitor that applies a search query to visitor data and * converts them to a QueryResultCommand. **/ -class SearchVisitor : public storage::Visitor { +class SearchVisitor : public storage::Visitor, + public SearchMethodInfo { public: SearchVisitor(storage::StorageComponent&, storage::VisitorEnvironment& vEnv, const vdslib::Parameters & params); @@ -253,19 +255,15 @@ private: * @param docsumSpec config with the field names used by the docsum setup. * @param fieldList list of field names that are built. **/ - static void registerAdditionalFields(const std::vector<vsm::DocsumTools::FieldSpec> & docsumSpec, - std::vector<vespalib::string> & fieldList); + static std::vector<vespalib::string> registerAdditionalFields(const std::vector<vsm::DocsumTools::FieldSpec> & docsumSpec); /** * Setup the field searchers used when matching the query with the stream of documents. * This includes setting up various mappings in FieldSearchSpecMap and building mapping * for fields used by the query. * - * @param additionalFields list of additional field names used when setting up the mappings. - * @param fieldsInQuery mapping from field name to field id that are built based on the query. **/ - void setupFieldSearchers(const std::vector<vespalib::string> & additionalFields, - vsm::StringFieldIdTMap & fieldsInQuery); + vsm::StringFieldIdTMap setupFieldSearchers(); /** * Prepare the field searchers for the given query. @@ -488,6 +486,7 @@ private: vsm::StringFieldIdTMapT _fieldsUnion; void setupAttributeVector(const vsm::FieldPath &fieldPath); + bool is_text_matching(vespalib::stringref index) const noexcept override; }; class SearchVisitorFactory : public storage::VisitorFactory { diff --git a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp index e33408a2e26..4b0efd58a56 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp +++ b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.cpp @@ -28,7 +28,8 @@ namespace vsm { namespace { -void setMatchType(FieldSearcherContainer & searcher, vespalib::stringref arg1) { +void +setMatchType(FieldSearcherContainer & searcher, vespalib::stringref arg1) { if (arg1 == "prefix") { searcher->setMatchType(FieldSearcher::PREFIX); } else if (arg1 == "substring") { @@ -44,14 +45,14 @@ void setMatchType(FieldSearcherContainer & searcher, vespalib::stringref arg1) { } -FieldSearchSpec::FieldSearchSpec() : - _id(0), - _name(), - _maxLength(0x100000), - _searcher(), - _searchMethod(VsmfieldsConfig::Fieldspec::Searchmethod::NONE), - _arg1(), - _reconfigured(false) +FieldSearchSpec::FieldSearchSpec() + : _id(0), + _name(), + _maxLength(0x100000), + _searcher(), + _searchMethod(VsmfieldsConfig::Fieldspec::Searchmethod::NONE), + _arg1(), + _reconfigured(false) { } FieldSearchSpec::~FieldSearchSpec() = default; @@ -150,7 +151,8 @@ FieldSearchSpec::reconfig(const QueryTerm & term) } } -vespalib::asciistream & operator <<(vespalib::asciistream & os, const FieldSearchSpec & f) +vespalib::asciistream & +operator <<(vespalib::asciistream & os, const FieldSearchSpec & f) { os << f._id << ' ' << f._name << ' '; if ( ! f._searcher) { @@ -171,7 +173,8 @@ namespace { const std::regex _G_array("\\[[0-9]+\\]"); } -vespalib::string FieldSearchSpecMap::stripNonFields(const vespalib::string & rawIndex) +vespalib::string +FieldSearchSpecMap::stripNonFields(vespalib::stringref rawIndex) { if ((rawIndex.find('[') != vespalib::string::npos) || (rawIndex.find('{') != vespalib::string::npos)) { std::string index = std::regex_replace(std::string(rawIndex), _G_map1, _G_value); @@ -182,44 +185,48 @@ vespalib::string FieldSearchSpecMap::stripNonFields(const vespalib::string & raw return rawIndex; } -bool FieldSearchSpecMap::buildFieldsInQuery(const Query & query, StringFieldIdTMap & fieldsInQuery) const +void +FieldSearchSpecMap::addFieldsFromIndex(vespalib::stringref rawIndex, StringFieldIdTMap & fieldIdMap) const { + for (const auto & dtm : documentTypeMap()) { + const IndexFieldMapT & fim = dtm.second; + vespalib::string index(stripNonFields(rawIndex)); + auto fIt = fim.find(index); + if (fIt != fim.end()) { + for(FieldIdT fid : fIt->second) { + const FieldSearchSpec & spec = specMap().find(fid)->second; + LOG(debug, "buildFieldsInQuery = rawIndex='%s', index='%s'", rawIndex.data(), index.c_str()); + if ((rawIndex != index) && (spec.name().find(index) == 0)) { + vespalib::string modIndex(rawIndex); + modIndex.append(spec.name().substr(index.size())); + fieldIdMap.add(modIndex, spec.id()); + } else { + fieldIdMap.add(spec.name(),spec.id()); + } + } + } else { + LOG(warning, "No valid indexes registered for index %s", rawIndex.data()); + } + } +} + +StringFieldIdTMap +FieldSearchSpecMap::buildFieldsInQuery(const Query & query) const { - bool retval(true); + StringFieldIdTMap fieldsInQuery; ConstQueryTermList qtl; query.getLeaves(qtl); for (const auto & term : qtl) { - for (const auto & dtm : documentTypeMap()) { - const IndexFieldMapT & fim = dtm.second; - vespalib::string rawIndex(term->index()); - vespalib::string index(stripNonFields(rawIndex)); - auto fIt = fim.find(index); - if (fIt != fim.end()) { - for(FieldIdT fid : fIt->second) { - const FieldSearchSpec & spec = specMap().find(fid)->second; - LOG(debug, "buildFieldsInQuery = rawIndex='%s', index='%s'", rawIndex.c_str(), index.c_str()); - if ((rawIndex != index) && (spec.name().find(index) == 0)) { - vespalib::string modIndex(rawIndex); - modIndex.append(spec.name().substr(index.size())); - fieldsInQuery.add(modIndex, spec.id()); - } else { - fieldsInQuery.add(spec.name(),spec.id()); - } - } - } else { - LOG(warning, "No valid indexes registered for index %s", term->index().c_str()); - retval = false; - } - } + addFieldsFromIndex(term->index(), fieldsInQuery); } - return retval; + return fieldsInQuery; } -void FieldSearchSpecMap::buildFromConfig(const std::vector<vespalib::string> & otherFieldsNeeded) +void +FieldSearchSpecMap::buildFromConfig(const std::vector<vespalib::string> & otherFieldsNeeded) { - for(size_t i(0), m(otherFieldsNeeded.size()); i < m; i++) { - LOG(debug, "otherFieldsNeeded[%zd] = '%s'", i, otherFieldsNeeded[i].c_str()); - _nameIdMap.add(otherFieldsNeeded[i]); + for (const auto & i : otherFieldsNeeded) { + _nameIdMap.add(i); } } @@ -253,7 +260,8 @@ buildFieldSet(const VsmfieldsConfig::Documenttype::Index & ci, const FieldSearch } -bool FieldSearchSpecMap::buildFromConfig(const VsmfieldsHandle & conf) +bool +FieldSearchSpecMap::buildFromConfig(const VsmfieldsHandle & conf) { bool retval(true); LOG(spam, "Parsing %zd fields", conf->fieldspec.size()); @@ -297,12 +305,14 @@ FieldSearchSpecMap::reconfigFromQuery(const Query & query) } } -bool lesserField(const FieldSearcherContainer & a, const FieldSearcherContainer & b) +bool +lesserField(const FieldSearcherContainer & a, const FieldSearcherContainer & b) { return a->field() < b->field(); } -void FieldSearchSpecMap::buildSearcherMap(const StringFieldIdTMapT & fieldsInQuery, FieldIdTSearcherMap & fieldSearcherMap) +void +FieldSearchSpecMap::buildSearcherMap(const StringFieldIdTMapT & fieldsInQuery, FieldIdTSearcherMap & fieldSearcherMap) const { fieldSearcherMap.clear(); for (const auto & entry : fieldsInQuery) { @@ -331,7 +341,8 @@ FieldSearchSpecMap::get_distance_metric(const vespalib::string& name) const return vsm::NearestNeighborFieldSearcher::distance_metric_from_string(itr->second.get_arg1()); } -vespalib::asciistream & operator <<(vespalib::asciistream & os, const FieldSearchSpecMap & df) +vespalib::asciistream & +operator <<(vespalib::asciistream & os, const FieldSearchSpecMap & df) { os << "DocumentTypeMap = \n"; for (const auto & dtm : df.documentTypeMap()) { diff --git a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.h b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.h index b0154a82dae..43bb5b04481 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.h +++ b/streamingvisitors/src/vespa/vsm/vsm/fieldsearchspec.h @@ -23,6 +23,11 @@ public: bool valid() const { return static_cast<bool>(_searcher); } size_t maxLength() const { return _maxLength; } bool uses_nearest_neighbor_search_method() const noexcept { return _searchMethod == VsmfieldsConfig::Fieldspec::Searchmethod::NEAREST_NEIGHBOR; } + bool uses_string_search_method() const noexcept { + return (_searchMethod == VsmfieldsConfig::Fieldspec::Searchmethod::UTF8) || + (_searchMethod == VsmfieldsConfig::Fieldspec::Searchmethod::AUTOUTF8) || + (_searchMethod == VsmfieldsConfig::Fieldspec::Searchmethod::SSE2UTF8); + } const vespalib::string& get_arg1() const noexcept { return _arg1; } /** @@ -71,17 +76,13 @@ public: * Adds a [field name, field id] entry to the given mapping for each field name used in the given query. * This is achieved by mapping from query term index name -> list of field ids -> [field name, field id] pairs. **/ - bool buildFieldsInQuery(const search::streaming::Query & query, StringFieldIdTMap & fieldsInQuery) const; - - /** - * Adds a [field name, field id] entry to the given mapping for each field name in the given vector. - **/ - void buildFieldsInQuery(const std::vector<vespalib::string> & otherFieldsNeeded, StringFieldIdTMap & fieldsInQuery) const; + StringFieldIdTMap buildFieldsInQuery(const search::streaming::Query & query) const; + void addFieldsFromIndex(vespalib::stringref index, StringFieldIdTMap & fieldIdMap) const; /** * Adds a FieldSearcher object to the given field searcher map for each field name in the other map. **/ - void buildSearcherMap(const StringFieldIdTMapT & fieldsInQuery, FieldIdTSearcherMap & fieldSearcherMap); + void buildSearcherMap(const StringFieldIdTMapT & fieldsInQuery, FieldIdTSearcherMap & fieldSearcherMap) const; const FieldSearchSpecMapT & specMap() const { return _specMap; } //const IndexFieldMapT & indexMap() const { return _documentTypeMap.begin()->second; } @@ -89,7 +90,7 @@ public: const StringFieldIdTMap & nameIdMap() const { return _nameIdMap; } friend vespalib::asciistream & operator <<(vespalib::asciistream & os, const FieldSearchSpecMap & f); - static vespalib::string stripNonFields(const vespalib::string & rawIndex); + static vespalib::string stripNonFields(vespalib::stringref rawIndex); search::attribute::DistanceMetric get_distance_metric(const vespalib::string& name) const; private: diff --git a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt index ad044ceca01..472b926b5a1 100644 --- a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt +++ b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt @@ -4,8 +4,6 @@ ai.djl.huggingface:tokenizers:${huggingface.vespa.version} ai.djl:api:${huggingface.vespa.version} aopalliance:aopalliance:${aopalliance.vespa.version} backport-util-concurrent:backport-util-concurrent:3.1 -ch.qos.logback:logback-classic:${logback.vespa.version} -ch.qos.logback:logback-core:${logback.vespa.version} classworlds:classworlds:1.1-alpha-2 com.amazonaws:aws-java-sdk-core:${aws-sdk.vespa.version} com.amazonaws:aws-java-sdk-kms:${aws-sdk.vespa.version} diff --git a/zookeeper-server/zookeeper-server/pom.xml b/zookeeper-server/zookeeper-server/pom.xml index 77aec63a781..bb4a819b5ac 100644 --- a/zookeeper-server/zookeeper-server/pom.xml +++ b/zookeeper-server/zookeeper-server/pom.xml @@ -45,14 +45,6 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - </exclusion> - <exclusion> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - </exclusion> </exclusions> </dependency> <!-- snappy-java and metrics-core are included here |